客户要求我计算机器和用户的平均登录时间。到目前为止,我发现该事件记录了一些启动时间比在以下位置找到的键设置的阈值更长的时间:
HKLM\Software\Microsoft\Windows\CurrentVersion\Diagnostics\Performance\Boot
但是这些键似乎被锁定,因此我无法编辑它们以降低阈值以确保记录每次启动。是否有任何方法可以为每次登录查找登录时间,该方法足够详细以告诉正在登录的用户以及可能的更详细信息,这也需要足够轻以在每次登录时运行,并且不会对用户造成明显影响.
最近我被要求做一件非常类似的事情,但要包括启动和登录时间并允许历史参考。所以下面的 powershell 脚本执行以下操作:
因此,如果您可能有 SCCM,则该脚本旨在通过计划任务或按某个计划运行(不在登录期间运行,以免根本不更改登录)。好处是您可以将 PCname 更改为其他任何名称,以便从您自己的 PC 上运行它并从远程计算机获取数据(尽管用户名会显示为您自己的)以排除故障并验证数字。
我又采取了一步,使用 SharePoint 创建外部数据列表(使用 BCS),这样他们就有了一个很好的前端 GUI。在下面的脚本中,我保留了编写脚本时使用的大部分注释行:
$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()
Run Code Online (Sandbox Code Playgroud)
在最后一个 SQL 部分中,有几行注释掉了,提供了另一种方法(基于安全的)来输入 SQL,而无需使用明文密码。