2

我一直在编写一个脚本来从事件日志中提取登录/注销历史记录。问题是我发现的几乎每个代码示例都使用“Get-EventLog”,它确实有效,但由于服务器上的事件日志比典型的工作站大得多,因此处理速度非常慢。因此,我选择了“Get-WinEvent”,因为它提供了非常相似的结果,但会在几秒钟内返回结果。我遇到的问题是将所述结果的输出操作为可用的形式。非常感谢任何帮助!

更新:我能够自己慢慢解决这个问题。详情见评论。感谢任何正在调查此问题的人:)

原始工作代码(Get-EventLog - 慢速输出)

function get-logonhistory{
 cls
 $Result = @()
 Write-Host "Gathering Event Logs, this can take awhile..."
 $ELogs = Get-EventLog System -Source Microsoft-Windows-WinLogon
 If ($ELogs)
 { Write-Host "Processing..."
 ForEach ($Log in $ELogs)
 { If ($Log.InstanceId -eq 7001)
   { $ET = "Logon"
   }
   ElseIf ($Log.InstanceId -eq 7002)
   { $ET = "Logoff"
   }
   Else
   { Continue
   }
   $Result += New-Object PSObject -Property @{
    Time = $Log.TimeWritten
    'Event Type' = $ET
    User = (New-Object System.Security.Principal.SecurityIdentifier $Log.ReplacementStrings[1]).Translate([System.Security.Principal.NTAccount])
   }
 }
 $Result | Select Time,"Event Type",User | Sort Time -Descending | Out-GridView
 Write-Host "Done."
 }
 Else
 { Write-Host "There was a problem reading the logs..."
 }
}


get-logonhistory

(Get-WinEvent) - 几乎即时的结果

function get-logonhistory{
 cls
 $Result = @()
 Write-Host "Gathering Event Logs, this can take awhile..."
 $ELogs = Get-WinEvent -ea SilentlyContinue ` -ProviderName “Microsoft-Windows-Winlogon”| Where-Object { $_.TimeCreated -le [datetime]::today}
 If ($ELogs)
 { Write-Host "Processing..."
 ForEach ($Log in $ELogs)
 { If ($Log.Id -eq 7001)
   { $ET = "Logon"
   }
   ElseIf ($Log.Id -eq 7002)
   { $ET = "Logoff"
   }
   Else
   { Continue
   }
   $SID = $Log.Properties.Value.Value
   $objSID = New-Object System.Security.Principal.SecurityIdentifier $SID
   $objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
   $Result += New-Object PSObject -Property @{
    Time = $Log.TimeCreated
    'Event Type' = $ET
    User = $objUser.Value
   }
 }
 $Result | Select Time,"Event Type",User | Sort Time -Descending | Out-GridView
 Write-Host "Done."
 }
 Else
 { Write-Host "There was a problem reading the logs..."
 }
}


get-logonhistory
4

1 回答 1

3

Get-WinEvent 和 Get-EventLog 使用不同的数组来存储事件日志的详细信息。Get-WinEvent 用户“Properties”和 Get-EventLog 用户“ReplacementStrings”。通过将每个转换为 JSON,您可以查看每个的确切详细信息,并找到您要查找的数据。在这种情况下,它是执行事件的帐户的 SID。一旦获得此信息,我们就可以将该 SID 转换为用户名并将其输入结果中。选择了 Grid-View 以获得更好的可用性,因此您可以在需要时过滤结果(即想要特定用户的事件)。以下是最终代码;

function get-logonhistory{
 cls
 $Result = @()
 Write-Host "Gathering Event Logs, this can take awhile..."
 $ELogs = Get-WinEvent -ea SilentlyContinue ` -ProviderName “Microsoft-Windows-Winlogon”| Where-Object { $_.TimeCreated -le [datetime]::today}
 If ($ELogs)
 { Write-Host "Processing..."
 ForEach ($Log in $ELogs)
 { If ($Log.Id -eq 7001)
   { $ET = "Logon"
   }
   ElseIf ($Log.Id -eq 7002)
   { $ET = "Logoff"
   }
   Else
   { Continue
   }
   $SID = $Log.Properties.Value.Value
   $objSID = New-Object System.Security.Principal.SecurityIdentifier $SID
   $objUser = $objSID.Translate( [System.Security.Principal.NTAccount])
   $Result += New-Object PSObject -Property @{
    'Date/Time' = $Log.TimeCreated
    'Event Type' = $ET
    User = $objUser.Value
   }
 }
 $Result | Select "Date/Time","Event Type",User | Sort Time -Descending | Out-GridView -Title "System Logon Events"
 Write-Host "Done."
 }
 Else
 { Write-Host "There was a problem reading the logs..."
 }
}


get-logonhistory
于 2019-11-29T18:10:57.773 回答