В составе SysInternals Suite помимо прочего есть такая утилита, как PsLoggedOn, отображающая, как несложно догадаться из названия, время входя в систему пользователя, — весьма полезная информация для системного администратора. Но суть скорее здесь в том, как вышеобозначенная утилита получает эти сведения, а способов между тем довольно много: от считывания времени модификации ключа реестра HKEY_CURRENT_USERVolatile Environment до задействования таких API-функций как LsaEnumerateLogonSessions, LsaFreeReturnBuffer, LsaGetLogonSessionData, — но то все про различные языки программирования. Как на счет штатных средств, но без WMI?
Остановил свой выбор я на VBScript, и если кто-то поморщит нос при упомянании последнего, дескать, это что-то из рода некрофилии, позвольте напомнить, что еще довольно много пользователей Windows использующих ХР, причем далеко не у всех них установлен PowerShell. В виду чего выбор считаю оправданным.
Одним из условий, которое было поставлено — не использовать WMI. Несложно догадаться, что в таком случае будем ковырять реестр. Не то, чтобы в забой по стахановски, нужны будут лишь такие ветви реестра, как HKEY_LOCAL_MACHINESYSTEMCurrentControlSetControlTimeZoneInformation и HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionProfileList. В первой нас интересует параметр ActiveTimeBias (смещение относительно часового пояса), во втором — ProfileLoadTimeLow и ProfileLoadTimeHigh текущего пользователя, представляющих собой поля структуры FILETIME. Все просто. Единственное, что может вызвать затруднение — как найти текущего пользователя, если WSH предоставляет доволько скудные возможности по работе с реестром? Будем использовать утилиту reg.exe из стандартной поставки Windows.
Dim objBias, strType, objExec, objData, objRexp, strUser
Dim tz, i, lowPart, highPart
With CreateObject("WScript.Shell")
objBias = .RegRead("HKLMSYSTEMCurrentControlSetControlTimeZoneInformationActiveTimeBias")
strType = UCase(TypeName(objBias))
If strType = "LONG" Then
tz = objBias
ElseIf strType = "VARIANT()" Then
tz = 0
For i = 0 To UBound(objBias)
tz = tz + (objBias(i) * 256 ^ i)
Next
End If
'ищем пользователя по имени
Set objExec = .Exec("cmd /q /k echo off")
objExec.StdIn.WriteLine _
"reg query ""HKLMSOFTWAREMicrosoftWindows NTCurrentVersionProfileList"" /s & exit"
objData = Split(objExec.StdOut.ReadAll, vbCrLf)
Set objRexp = New RegExp
objRexp.Pattern = CreateObject("WScript.Network").UserName
objRexp.IgnoreCase = True
objRexp.Global = True
For i = 0 To UBound(objData)
If objRexp.Test(objData(i)) Then
strUser = objData(i - 1)
Exit For
End If
Next
'strUser = HKLMSOFTWAREMicrosoftWindows NTCurrentVersionProfileListSID
lowPart = .RegRead(strUser & "ProfileLoadTimeLow")
highPart = .RegRead(strUser & "ProfileLoadTimeHigh")
'конвертируем поля FILETIME в дату
WScript.Echo ((highPart * (2 ^ 32) + lowPart) / (60 * 10000000) - tz) / 1440 + #1/1/1601#
End With