优化PowerShell性能和内存消耗

时间:2016-10-01 08:15:21

标签: powershell csv out-of-memory audit

下面的PowerShell脚本在一个或多个服务器上查询ID为4663的事件的安全事件日志。当尝试使用以下代码检索事件id 4663的所有审核事件时,计算机会抛出以下异常:我们如何优化这个PowerShell? 所以我只想基于特定的AD用户而不是所有用户来获取安全事件日志。否则我想找回我需要的东西。

enter image description here enter image description here

$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:\TEMP\4663Events.csv

1 个答案:

答案 0 :(得分:1)

重构代码,以便偶尔刷新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:\TEMP\4663Events.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:\TEMP\4663Events.csv -append

修改

由于错误来自Out-LineOutput,这是一个internal cmdlet,它可能与shell内存设置有关。您可以尝试将每个shell的最大内存增加到2 GB。像这样,

Set-Item .\MaxMemoryPerShellMB 2048

MS Scripting Guys博客有关于配置限制的detailed article