优化 PowerShell 性能和内存消耗
Optimize PowerShell Performance and Memory Consumption
下面的 PowerShell 脚本在一台或多台服务器上的安全事件日志中查询 ID 为 4663 的事件。当尝试使用以下代码检索事件 ID 4663 的所有审核事件时,计算机抛出以下异常:我们如何才能优化这个PowerShell?
所以我只想根据特定的 AD 用户而不是所有用户来获取安全事件日志。否则我想取回我需要的东西。
$server = "HOSTNAME"
$out = New-Object System.Text.StringBuilder
$out.AppendLine("ServerName,EventID,TimeCreated,UserName,File_or_Folder,AccessMask")
$ns = @{e = "http://schemas.microsoft.com/win/2004/08/events/event"}
foreach ($svr in $server)
{ $evts = Get-WinEvent -computer $svr -FilterHashtable @{logname="security";id="4663"} -oldest
foreach($evt in $evts)
{
$xml = [xml]$evt.ToXml()
$SubjectUserName = Select-Xml -Xml $xml -Namespace $ns -XPath "//e:Data[@Name='SubjectUserName']/text()" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty Value
$ObjectName = Select-Xml -Xml $xml -Namespace $ns -XPath "//e:Data[@Name='ObjectName']/text()" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty Value
$AccessMask = Select-Xml -Xml $xml -Namespace $ns -XPath "//e:Data[@Name='AccessMask']/text()" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty Value
$out.AppendLine("$($svr),$($evt.id),$($evt.TimeCreated),$SubjectUserName,$ObjectName,$AccessMask")
Write-Host $svr
Write-Host $evt.id,$evt.TimeCreated,$SubjectUserName,$ObjectName,$AccessMask
}
}
$out.ToString() | out-file -filepath C:\TEMP63Events.csv
重构代码,以便不时刷新 stringbuilder 内容。这使它的大小更易于管理。像这样,
$out = New-Object System.Text.StringBuilder
$out.AppendLine("ServerName,EventID,TimeCreated,UserName,File_or_Folder,AccessMask")
foreach($evt in $evts) {
$xml = [xml]$evt.ToXml()
...
$out.AppendLine("$($svr),$($evt.id),$($evt.TimeCreated),$SubjectUserName,$ObjectName,$AccessMask")
# If the stringbuffer is large enough, flush its contents to disk
# and start filling empty buffer again
if($out.length -ge 100MB) {
$out.ToString() | out-file -filepath C:\TEMP63Events.csv -append
$out.Clear()
}
}
# Remember to flush the buffer so that stuff that wasn't flushed in the
# foreach loop is saved as well
$out.ToString() | out-file -filepath C:\TEMP63Events.csv -append
编辑:
由于错误来自 Out-LineOutput
,这是一个 internal cmdlet,它可能与 shell 内存设置有关。您可以尝试将每个 shell 的最大内存增加到 2 GB。像这样,
Set-Item .\MaxMemoryPerShellMB 2048
MS Scripting Guys 博客有一个detailed article关于配置限制
下面的 PowerShell 脚本在一台或多台服务器上的安全事件日志中查询 ID 为 4663 的事件。当尝试使用以下代码检索事件 ID 4663 的所有审核事件时,计算机抛出以下异常:我们如何才能优化这个PowerShell? 所以我只想根据特定的 AD 用户而不是所有用户来获取安全事件日志。否则我想取回我需要的东西。
$server = "HOSTNAME"
$out = New-Object System.Text.StringBuilder
$out.AppendLine("ServerName,EventID,TimeCreated,UserName,File_or_Folder,AccessMask")
$ns = @{e = "http://schemas.microsoft.com/win/2004/08/events/event"}
foreach ($svr in $server)
{ $evts = Get-WinEvent -computer $svr -FilterHashtable @{logname="security";id="4663"} -oldest
foreach($evt in $evts)
{
$xml = [xml]$evt.ToXml()
$SubjectUserName = Select-Xml -Xml $xml -Namespace $ns -XPath "//e:Data[@Name='SubjectUserName']/text()" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty Value
$ObjectName = Select-Xml -Xml $xml -Namespace $ns -XPath "//e:Data[@Name='ObjectName']/text()" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty Value
$AccessMask = Select-Xml -Xml $xml -Namespace $ns -XPath "//e:Data[@Name='AccessMask']/text()" | Select-Object -ExpandProperty Node | Select-Object -ExpandProperty Value
$out.AppendLine("$($svr),$($evt.id),$($evt.TimeCreated),$SubjectUserName,$ObjectName,$AccessMask")
Write-Host $svr
Write-Host $evt.id,$evt.TimeCreated,$SubjectUserName,$ObjectName,$AccessMask
}
}
$out.ToString() | out-file -filepath C:\TEMP63Events.csv
重构代码,以便不时刷新 stringbuilder 内容。这使它的大小更易于管理。像这样,
$out = New-Object System.Text.StringBuilder
$out.AppendLine("ServerName,EventID,TimeCreated,UserName,File_or_Folder,AccessMask")
foreach($evt in $evts) {
$xml = [xml]$evt.ToXml()
...
$out.AppendLine("$($svr),$($evt.id),$($evt.TimeCreated),$SubjectUserName,$ObjectName,$AccessMask")
# If the stringbuffer is large enough, flush its contents to disk
# and start filling empty buffer again
if($out.length -ge 100MB) {
$out.ToString() | out-file -filepath C:\TEMP63Events.csv -append
$out.Clear()
}
}
# Remember to flush the buffer so that stuff that wasn't flushed in the
# foreach loop is saved as well
$out.ToString() | out-file -filepath C:\TEMP63Events.csv -append
编辑:
由于错误来自 Out-LineOutput
,这是一个 internal cmdlet,它可能与 shell 内存设置有关。您可以尝试将每个 shell 的最大内存增加到 2 GB。像这样,
Set-Item .\MaxMemoryPerShellMB 2048
MS Scripting Guys 博客有一个detailed article关于配置限制