Меня недавно попросили сделать очень похожую вещь, но включить время загрузки и входа в систему и учесть историческую справку. поэтому приведенный ниже скрипт powershell выполняет следующие действия:
- захватывает некоторые переменные среды
- получает метку времени \ даты для 4 разных записей журнала событий. 2-й и 4-й из них не являются точными измерениями, но после довольно обширных исследований, поиска неисправностей и тестирования они очень близки и, как я видел, лучшие варианты.
- вычисляет разницу между этими 4 событиями
- заполняет все числа в простую таблицу SQL [вы, конечно, можете приспособить их для преобразования чисел во что угодно]
Таким образом, сценарий предназначен для выполнения через запланированное задание или по какому-либо расписанию, если у вас, возможно, есть SCCM (не во время входа в систему, чтобы вообще не изменять вход в систему). приятно то, что вы можете изменить имя ПК на любое другое, чтобы запустить его со своего ПК и получить данные с удаленного компьютера (хотя имя пользователя будет отображаться как ваше собственное) для устранения неполадок и проверки номеров.
Я сделал еще один шаг и использовал SharePoint, чтобы создать список внешних данных (используя BCS), чтобы у них был приятный графический интерфейс. Сценарий ниже, я оставил в большинстве закомментированных строк, которые я использовал при написании:
$USER = $env:username.ToUpper()
$COMPUTER = $env:computername.ToUpper()
$Current_Time = Get-Date
$PCname = ''
$addedtime = 0
#1. get event time of last OS load
$filterXML = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Kernel-General'] and (Level=4 or Level=0) and (EventID=12)]]</Select>
</Query>
</QueryList>
'@
$OSLoadTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML).timecreated
#Write-Host $PCname
#Write-Host "1. Last System Boot @ " $OSLoadTime
#2. Get event time of Time-Service [pre-Ctrl+Alt-Del] after latest OS load
$filterXML = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Time-Service'] and (Level=4 or Level=0) and (EventID=35)]]</Select>
</Query>
</QueryList>
'@
$CtrlAltDelTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML).timecreated
#Write-Host "2. Time-sync after Boot @ " $CtrlAltDelTime
#get minutes (rounded to 1 decimal) between OS load time and 1st load of GPOs
$BootDuration = "{0:N1}" -f ((($CtrlAltDelTime - $OSLoadTime).TotalSeconds + $addedtime)/60)
#3. get event time of 1st successful logon
$filterXML = @'
<QueryList>
<Query Id="0" Path="System">
<Select Path="System">*[System[Provider[@Name='Microsoft-Windows-Winlogon'] and (Level=4 or Level=0) and (EventID=7001)]]</Select>
</Query>
</QueryList>
'@
$LogonDateTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML -ErrorAction SilentlyContinue).timecreated
If ($LogonDateTime) {
#Write-Host "3. Successful Logon @ " $LogonDateTime
}
Else {
#Write-Host "Duration of Bootup = " $BootDuration "minutes" -foregroundcolor blue -BackgroundColor white
#Write-Host $PCname "has not logged back in." -foregroundcolor red -BackgroundColor white
Exit
}
#Write-Host "Duration of Bootup = " $BootDuration "minutes" -foregroundcolor blue -BackgroundColor white
#4. Get Win License validated after logon (about same time as explorer loads)
$filterXML = @'
<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">*[System[Provider[@Name='Microsoft-Windows-Winlogon'] and (Level=4 or Level=0) and (EventID=4101)]]</Select>
</Query>
</QueryList>
'@
$DesktopTime=(Get-WinEvent -ComputerName $PCname -MaxEvents 1 -FilterXml $filterXML).timecreated
$LogonDuration = "{0:N1}" -f ((($DesktopTime - $LogonDateTime).TotalSeconds + $addedtime)/60)
#Write-Host "4. WinLicVal after Logon @ " $DesktopTime
#Write-Host "Duration of Logon = " $LogonDuration "minutes" -foregroundcolor blue -BackgroundColor white
#START SQL Injection Section
[void][reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$sqlServer = "SQLserver01"
$dbName = "BootUpTimes"
$tbl = "tblBootUpTimes"
#$srv = New-Object Microsoft.SqlServer.Management.Smo.Server $sqlServer
#$db = $srv.databases[$dbName]
#$conn = New-Object System.Data.SqlClient.SqlConnection("Data Source=$sqlServer;Initial Catalog=$dbName; Integrated Security=SSPI")
$conn = New-Object System.Data.SqlClient.SqlConnection("server=$sqlServer;database=$dbName;Password=plaintext;User Id=BootUpTimes")
$conn.Open()
$cmd = $conn.CreateCommand()
$cmd.CommandText = "INSERT INTO $tbl VALUES ('$Current_Time','$USER','$COMPUTER','$OSLoadTime','$CtrlAltDelTime','$BootDuration','$LogonDateTime','$DesktopTime','$LogonDuration')"
Try
{
$null = $cmd.ExecuteNonQuery()
}
Catch
{
}
$conn.Close()
В этом последнем разделе SQL есть несколько закомментированных строк, предлагающих другой метод (основанный на безопасности) для ввода в SQL без необходимости ввода пароля в открытом тексте.