Gần đây tôi đã được yêu cầu làm một điều rất giống nhưng bao gồm thời gian khởi động và đăng nhập và cho phép tham khảo lịch sử. Vì vậy, tập lệnh powershell dưới đây thực hiện như sau:
- lấy một số biến môi trường
- lấy dấu thời gian \ ngày cho 4 mục nhật ký sự kiện khác nhau. Lần thứ 2 và thứ 4 trong số này không phải là các phép đo chính xác nhưng sau khi nghiên cứu sâu rộng, xử lý sự cố và kiểm tra chúng rất gần và từ những gì tôi đã thấy, các lựa chọn tốt nhất.
- tính toán sự khác biệt giữa 4 sự kiện này
- điền tất cả các số vào một bảng SQL đơn giản [bạn có thể điều chỉnh để chuyển các số thành bất cứ thứ gì bạn muốn].
Vì vậy, tập lệnh có nghĩa là chạy qua tác vụ theo lịch trình hoặc theo lịch trình nào đó nếu bạn có SCCM (không phải trong quá trình đăng nhập để không thay đổi đăng nhập). điều tuyệt vời là bạn có thể thay đổi PCname thành bất kỳ thứ gì khác để chạy nó từ PC của chính bạn và lấy dữ liệu từ một máy tính từ xa (mặc dù tên người dùng sẽ hiển thị là của riêng bạn) để khắc phục sự cố và xác minh các số.
Tôi đã thực hiện một bước nữa và sử dụng SharePoint để tạo danh sách dữ liệu ngoài (sử dụng BCS) để chúng có GUI giao diện người dùng đẹp. Kịch bản bên dưới, tôi đã để lại trong hầu hết các dòng nhận xét tôi đã sử dụng trong khi viết nó:
$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()
Trong phần SQL cuối cùng này, có một vài dòng nhận xét đưa ra một phương thức khác (dựa trên bảo mật) để nhập vào SQL mà không cần một số mật khẩu trong văn bản gốc.