1

Тема: VBScript Конвертирование даты из HEX в обычный формат

Столкнулся с такой проблемой. Многие программы хранят в реестре какую-то дату в виде HEX. В частности, у меня сейчас проблемы с симантеком, но даже сама винда часто так поступает (например, HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsBackup\Status, параметр Last Success)

И вот вижу я что-то типа 70 05 A0 27 9B CA C9 01 и знаю, что это 01.05.2009 20:26:49

Собственно, наполовину проблему я решил, т.к. алгоритм преобразования я нашел (может, кому пригодится)
Это т.н. FileTime, поступаем следующим образом - получаем HEX-число (01c9ca9b27a00570, да, младшее число становится старшим), потом переводим это в DEC (получаем 128856832090310000). Это WinNT time, из него можно получить нормальную дату (в частности, с помощью команды w32tm.exe /ntte 128856832090310000)

HEX-число я получаю (естественно, как стринг), для преобразования обычного DEC-числа в дату на этом же форуме я нашел замечательную функцию (из темы про получение времени последнего логина пользователей)

Function getLast( last )
    Dim intLastLogonTime
    intLastLogonTime = last.HighPart * (2^32) + last.LowPart
    intLastLogonTime = intLastLogonTime / (60 * 10000000)
    intLastLogonTime = intLastLogonTime / 1440
    if intLastLogonTime <> 0 then intLastLogonTime = intLastLogonTime + #1/1/1601#
    getLast = intLastLogonTime
End Function

так что затык только один - пробросить мостик между имеющимся у меня HEX и требуемым для getLast десятичным числом

попробовал поискать готовую функцию перевода HEX to DEC, но все они возвращают число типа Double вида
1.2885683209031E+17 и getLast это не понимает

Понимаю, что проблема звучит смешной, но функцию getLast я не понимаю и потому преобразовать число в понятный для ее работы вид не могу...

2

Re: VBScript Конвертирование даты из HEX в обычный формат

Вы путаете. getLast — функция, использовавшаяся в контексте перевода 8-байтной структуры FILETIME (параметр «last») в тип VarDate.

Для работы с этой структурой можно пользовать WMI, а конкретно — объект SWbemDateTime:

Option Explicit

Dim objSWbemDateTime
Dim strFILETIME

Set objSWbemDateTime = WScript.CreateObject("WbemScripting.SWbemDateTime")

strFILETIME = "128856832090310000"

With objSWbemDateTime
    .SetFileTime strFILETIME, True
    WScript.Echo .GetVarDate
End With

Set objSWbemDateTime = Nothing

WScript.Quit 0

Я у себя такого параметра не нашёл. Выложите сюда файл реестра с этим параметром, я тоже погляжу на возможные преобразования из значения реестра в строку.

3 (изменено: Rumata, 2009-06-23 19:01:47)

Re: VBScript Конвертирование даты из HEX в обычный формат

01c9ca9b27a00570, да, младшее число становится старшим

это называется LittleEndian Number. Почитать об этом можно здусь http://en.wikipedia.org/wiki/Endianness

Это WinNT time, из него можно получить нормальную дату

Это очень разочаровывает. MS как всегда впереди планеты всей и пытается изобрести нечто собственное. Timestamp тоже может показаться не самым удобным представлением, но оно все-таки привычное уже на протяжении почти 40 лет.

Спасибо. Ваше исследование очень полезно и может помочь.

( 2 * b ) || ! ( 2 * b )

4 (изменено: Alexx_B, 2009-06-24 09:57:15)

Re: VBScript Конвертирование даты из HEX в обычный формат

Для работы с этой структурой можно пользовать WMI, а конкретно — объект SWbemDateTime:

спасибо! это именно то, что надо

Я у себя такого параметра не нашёл. Выложите сюда файл реестра с этим параметром, я тоже погляжу на возможные преобразования из значения реестра в строку

это от ntbackup, если запланированы задания
но я привел это лишь как пример, что подобная кодировка используется в самой винде. Думаю, если поискать в реестре, то можно еще встретить подобные варианты записи даты

В моем же случае я искал способ конвертации значения параметра ServiceStartTimeFT и VirusDefinitionDateFileTime. Это значение от программы Symantec Mail Security, просто я предположил, что продукт более редкий, чем сама винда.
А вот вариант кодирования тот же

Если интересно - могу и поделиться, мне не жалко

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Symantec\SMSMSE\6.0\Server\Stats\ServerInfo]
"ServerNameStr"="server"
"ServiceStartTimeFT"=hex:70,05,a0,27,9b,ca,c9,01
"ExchangeServiceStateBool"=dword:00000000
"AutoProtectionStateEnum"=dword:00000002
"VirusScanningStateBool"=dword:00000001
"MailboxStoreTotalDword"=dword:00000000
"MailboxStoreMountedDword"=dword:00000000
"PublicFolderStoreTotalIDDword"=dword:00000000
"PublicFolderStoreMountedDword"=dword:00000000
"AutoProtectPolicyIDDword"=dword:00000000
"AutoProtectPolicyNameStr"="Standard"
"StandardVirusPolicyActionEnum"=dword:00000003
"TotalVirusDefinitionCount"=dword:0000941d
"VirusDefinitionVersionUint"=dword:00000002
"VirusDefinitionDateFileTime"=hex:20,8e,b4,62,cc,f2,c9,01

это называется LittleEndian Number

спасибо, буду знать

Спасибо. Ваше исследование очень полезно и может помочь.

не за что

не буду присваивать себе все лавры - на самом деле объяснение этому я нашел на сайте MS
http://social.msdn.microsoft.com/Forums/en-US/vblanguage/thread/b7fa5f6b-df8e-49fe-9b25-a0c6e3ac9dc5

но там решение было на VB, и решение:

DateTime.FromFileTimeUtc

не подошло

но сам принцип я понял именно оттуда

5

Re: VBScript Конвертирование даты из HEX в обычный формат

Alexx_B, у меня, увы, никак не получилось конвертировать полученный  из параметра REG_BINARY массив (представляющее то самое шестнадцатирично-десятичное значение Int64) в строку десятичных символов. Вы-то сие как делали?

6 (изменено: Alexx_B, 2009-06-25 10:07:30)

Re: VBScript Конвертирование даты из HEX в обычный формат

ну, я тоже не смог победить

в результате оказалось, что переводить в общем и не надо
можно сразу hex использовать:

Function HexDateToDate(hDate)
    highPart = CDbl("&h" & Left(hDate,8))
    lowPart = CDbl("&h" & Right(hDate,8))
    intInstalledOn = highPart * (2^32) + lowPart 
    intInstalledOn = intInstalledOn / (60 * 10000000)
    intInstalledOn = intInstalledOn / 1440
    HexDateToDate = intInstalledOn + #1/1/1601#
End Function

как легко понять, надо подавать ровно 16 знаков. У меня почему-то постоянно терялся первый нолик, поэтому я просто добивал слева нулями до тех пор, пока 16 символов не получалось

function ReadHexDataRegValues (RegRoot, RegValue)
    CurrentValue = WSHShell.RegRead(RegRoot & "\" & RegValue)
    For I = LBound(CurrentValue) To UBound(CurrentValue)
        tmphex = CStr(Hex(CurrentValue(I)))
        if Len(tmphex)=1 then tmphex = "0" & tmphex
        hexstr = tmphex & hexstr
    Next
    
    While Len(hexstr) <16
        hexstr = "0" & hexstr
    Wend
    ReadHexDataRegValues = HexDateToDate(hexstr)
End Function

наверняка можно было сделать и куда красивее, но мне важнее была скорость (в смысле чтобы скриптом можно было пользоваться быстрее)