所以我有這樣一個腳本,它通過Windows安全日志進行回圈,以檢查一個賬戶在過去7天內是否有任何活動(因為日志的保留期是7天--如果能在腳本中加入一個天數限制器,那就更棒了)。然而,每次運行需要6個小時(1,200萬個事件)。在事件查看器中列出這些事件只需要幾秒鐘的時間,這讓我相信我可以把代碼寫得更優化。對此有什么見解嗎?
代碼:
$filter = @{LogName='Security'; ProviderName='Microsoft-Windows-Security-Auditing'}。
$i = 0
$entries = Get-WinEvent -FilterHashtable $filter -ComputerName localhost | ForEach-Object{
$eventXml = ([xml]$_.ToXml() ).Event
$userName = ($eventXml.EventData. 資料|Where-Object { $_.Name -eq 'TargetUserName' }).'#text'。
$computer = ($eventXml.EventData. 資料|Where-Object { $_.Name -eq 'WorkstationName'}).'#text'。
If($userName -match "Username1" -or $userName - 變數">$userName -match "用戶名3")
{
[PSCustomObject]@{
時間 = [DateTime]$eventXml.System.TimeCreated.SystemTime
UserName = $userName。
計算機 = $computer。
}
}
$i
Write-Progress -activity "Scanning Win Events..." -status "Scanned: $i""。
}
$filetime = Get-Date -Format "ddMMyyyyHmm"/span>
$entries | Out-File "C:TempUsedAccounts$filetime.txt"
$endTime = (Get-Date)
'持續時間。{0:mm} min {0:ss} sec' -f ($endTime-$startTime)```。
uj5u.com熱心網友回復:
正如所評論的那樣,有一些方法可以加速事情的進展:
TargetUserName項。
ForEach-Object回圈改為foreach(),這比管道處理要快寫進度# filter on logon, because not all events would have a 'TargetUserName' item.
$filter = @{LogName='Security'; ProviderName='Microsoft-Windows-Security-Auditing'; ID=4624}。
$entries = foreach ($entry in (Get-WinEvent -FilterHashtable $filter -ComputerName localhost) {
$eventXml = ([xml]$entry.ToXml() ).Event
$userName = ($eventXml.EventData. 資料|Where-Object { $_.Name -eq 'TargetUserName' }).'#text'。
# 如果你需要 "全詞 "匹配,請改為 '#text'。
# $username -match '(Username1|Username2|Username3)'
if($userName -match ' Username1|Username2|Username3') {
$computer = ($eventXml.EventData. 資料|Where-Object { $_.Name -eq 'WorkstationName'}).'#text'。
# 輸出一個物件。
[PSCustomObject]@{
時間 = [DateTime]$eventXml.System.TimeCreated.SystemTime
UserName = $userName。
計算機 = $computer。
}
}
# don't waste time writing unnecessary stuff in the loop with
# Write-Progress或Write-Host。
}
# 現在將物件輸出到一個結構化的Csv檔案,你可以
# 雙擊以在Excel中打開。
$filetime = Get-Date -Format "ddMMyyyyHmm"
$entries | Export-Csv -Path "C:TempUsedAccounts$filetime.csv"/span> -UseCulture -NoTypeInformation
幾乎忘了。 你可以通過擴展過濾器將事件限制在過去7天內:
$filter = @{
LogName ='Security'/span>
ProviderName ='Microsoft-Windows-Security-Auditing'/span>
ID =4624
StartTime = (Get-Date).AddDays(-7).Date)
uj5u.com熱心網友回復:
Theo比我快,但除了他的建議外,我還建議使用-FilterXml如果你改用XML來做你的過濾器,而不是hashtable,你肯定可以改進你的過濾器選項,包括指定你的結果是多長時間。
$filter = @'
<QueryList>
< Query Id="0" Path="安全">
<Select Path="Security"/span>> *[System[TimeCreated[@SystemTime& gt;='2021-09-15T17: 39:00. 000Z']]</Select>。
</Query>/span>
</QueryList>/span>
'@
$entries = Get-WinEvent -FilterXml $filter
這將獲得安全日志中從今天上午10:39到現在的所有內容。你可以把它設定為你想要的任何日期/時間。它快嗎?不,它真的不快。加載10分鐘的日志資料,對我來說剛剛超過8200條,花了1分18秒。它比抓取整個日志快嗎?哦,嘿嘿,是的!我沒有讓它加載所有資料。我還沒有讓它加載我系統中的10.9萬個條目(我對檔案有100MB的限制),但我想它會相應地更長。
在這之前,我真的會考慮只對事件的訊息運行一個重碼匹配,而不是將所有內容轉換為 XML。誠然,您的大部分時間只是將事件輸入 PowerShell,但處理它們也需要時間,而僅僅針對訊息運行一個 regex 匹配,而不是將其轉換為 XML 并進行決議,這比轉換為 XML 并進行決議要長 60 倍(至少在我的開發盒上)。當然,這只是30毫秒對1829毫秒,但這是將8.2k事件減少到8個。如果是120萬個事件,這將會變得更加重要。由于這總是在本地機器上運行,你可以直接使用$env:COMPUTERNAME而不是從每個事件中提取計算機名稱。因此,在你得到你的事件日志條目之后,我會這樣做:
$filtered=ForEach($entry in $entries){
if($entry.Message -match "(?ms)目標主題:. ? 賬戶名稱:s (user1|user2|user3)"){
[pscustomobject]@{
TimeCreated=$entry.TimeCreated
User=$Matches[1]
Computer=$env:COMPUTERNAME
}
}
}
$filetime = Get-Date -Format "ddMMyyyyHmm"/span>
$filtered | Out-File "C:TempUsedAccounts$filetime.txt"
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/309298.html
標籤:
