Reputation: 1904
The PowerShell script below queries the Security event log on one or more servers for events with id 4663. When trying to retrieve all audit events for event id 4663 with the following code the computer throws the following exception: how can we to optimize this PowerShell? So I just want to fetch security event log based on specific AD Users instead of all of users. Otherwise I want to retrieve what I need.
$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
Upvotes: 1
Views: 1727
Reputation: 24071
Refactor the code so that the stringbuilder contents are flushed every now and then. This keeps its size more manageable. Like so,
$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
Edit:
As the error is coming from Out-LineOutput
, which is an internal cmdlet, it might be about the shell memory settings. You could try increasing the maximum memory per shell to, say 2 GB. Like so,
Set-Item .\MaxMemoryPerShellMB 2048
The MS Scripting Guys blog has a detailed article about configuring the limits
Upvotes: 2