Need to extract the XML data to CSV - powershell

I need to read specific information from event log. in below script I cannot export the some value contains in XML View. In the XML view I Want Target username: BRSYSAD and Subjectusername : 900011-LT
Script
$filter = "*[System[EventID=4740 and Provider[#Name='Microsoft-Windows-Security-Auditing']]]"
$result = Get-WinEvent -LogName Security -FilterXPath $filter | ForEach-Object {
# convert the event to XML and grab the Event node
$eventXml = ([xml]$_.ToXml()).Event
# output the properties you need
[PSCustomObject]#{
EventID = $eventXml.System.EventID.'#text'
TimeCreated = $eventXml.System.TimeCreated.SystemTime -replace '\.\d+.*$'
Computer = $eventXml.System.Computer
Data = $eventXml.EventData.Data
}
}
# output on screen
$result | Format-Table -AutoSize
# save as CSV file if you like
$result | Export-Csv -Path 'C:\MyProgr_Events_302.csv' -NoTypeInformation

You should be able to get the TargetUserName and SubjectUserName properties by filtering the EventData for those specifically named attributes.
Example code updated (I've also removed the .'#text' part from the EventID line to ensure this value is captured)
$filter = "*[System[EventID=4740 and Provider[#Name='Microsoft-Windows-Security-Auditing']]]"
$result = Get-WinEvent -LogName Security -FilterXPath $filter | ForEach-Object {
# convert the event to XML and grab the Event node
$eventXml = ([xml]$_.ToXml()).Event
# output the properties you need
[PSCustomObject]#{
EventID = $eventXml.System.EventID
TimeCreated = $eventXml.System.TimeCreated.SystemTime -replace '\.\d+.*$'
Computer = $eventXml.System.Computer
TargetUserName = ($eventXml.EventData.Data | Where-Object { $_.Name -eq "TargetUserName"}).'#text'
SubjectUserName = ($eventXml.EventData.Data | Where-Object { $_.Name -eq "SubjectUserName"}).'#text'
}
}
# output on screen
$result | Format-Table -AutoSize
# save as CSV file if you like
$result | Export-Csv -Path 'C:\MyProgr_Events_302.csv' -NoTypeInformation
If you prefer, you could pull out all attributes with the following instead:
$filter = "*[System[EventID=4740 and Provider[#Name='Microsoft-Windows-Security-Auditing']]]"
$result = Get-WinEvent -LogName Security -FilterXPath $filter | ForEach-Object {
# convert the event to XML and grab the Event node
$eventXml = ([xml]$_.ToXml()).Event
# output the properties you need
$object = [PSCustomObject]#{
EventID = $eventXml.System.EventID
TimeCreated = $eventXml.System.TimeCreated.SystemTime -replace '\.\d+.*$'
Computer = $eventXml.System.Computer
}
$eventXml.EventData.Data | ForEach-Object { $object | Add-Member -MemberType NoteProperty -Name $_.Name -Value $_.'#text' }
$object
}
# output on screen$
$result | Format-Table -AutoSize
You'd then end up with all the attributes available to you and each result would contain data such as:

Related

Duration of specific task in task scheduler

Taking inspiration on Get informations on Windows Scheduled Task duration (execution time)
we aim to filter on a set of tasks, instead of fetching all from task scheduler.
something of this sort:
$logName = 'Microsoft-Windows-TaskScheduler/Operational'
$xPathFilter = #'
*[
System[(EventID=200 or EventID=201)] and
EventData[
Data[#Name="TaskName"] = "001_task_A_nightly"
]
]
'#
Get-WinEvent -LogName $logName -FilterXPath $xPathFilter | Group-Object ActivityID | ForEach-Object {
$start = $_.Group |
Where-Object { $_.Id -eq 200 } |
Select-Object -Expand TimeCreated -First 1
$end = $_.Group |
Where-Object { $_.Id -eq 201 } |
Select-Object -Expand TimeCreated -First 1
New-Object -Type PSObject -Property #{
'TaskName' = $_.Group[0].Properties[0].Value
'Duration' = ($end - $start).TotalSeconds
Is there a way to adapt this one above?
Use the -FilterXPath parameter set instead, it'll allow you to granularly filter on the contents of the underlying event XML:
$logName = 'Microsoft-Windows-TaskScheduler/Operational'
$xPathFilter = #'
*[
System[(EventID=200 or EventID=201)] and
EventData[
Data[#Name="TaskName"] = "\MyTask" or
Data[#Name="TaskName"] = "\MyOtherTask" or
Data[#Name="TaskName"] = "\TaskFolder\SomeThirdTask"
]
]
'#
Get-WinEvent -LogName $logName -FilterXPath $xPathFilter |Group-Object ...

Format of the Export-Csv in Powershell - unexpected column order

I'm trying to export an array of objects to a .csv file, what do I need to do to put everything in the right column with header of a property name.
I've tried selecting properties by select to pipeline
$groups = Get-MsolGroup -All
$results = #()
foreach ($group in $groups) {
$props = #{
'DisplayName' = $group.DisplayName
'GroupType' = $group.GroupType
'Email' = $group.EmailAddress
'MemberCount' = #(Get-MsolGroupMember -GroupObjectId $group.ObjectId).Count
}
New-Object -Type PSObject -Prop $props
$results += $props
}
$results | Export-Csv -Path C:\Users\Tako\Desktop\results.csv -NoTypeInformation
You can use your code like below:
$groups = Get-MsolGroup -All
$output = $groups | ForEach-Object{
[PSCustomObject]#{
"DisplayName" = $_.DisplayName
"GroupType" = $_.GroupType
"Email" = $_.EmailAddress
"MemberCount" = #(Get-MsolGroupMember -GroupObjectId $_.ObjectId).Count
}
}
$output | Export-Csv -Path "F:\temp\1\myresults.csv" -NoTypeInformation
Here is a similar test, just test with Get-AzStorageAccount cmdlet:

How to fix Get-ChildItem -Recurse to handle more than the first level

I try to filter Windows events (id=4633) from eventlogs out of a given filestructure recursivly with Get-ChildItem.
The filestructure looks like this:
C:\Temp\raw_data\2018-09\Securitylog\Securitylog_2018-09-14_13-30.evtx
The problem is, that the Get-ChildItem only handles the first level. Every level below the first one seems to be ignored.
I tried using the -Recurse parameter without success. I don't receive any errors, so I believe the syntax is correct. The codesample is given below.
$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"}
Get-ChildItem "C:\temp\raw_data" -Recurse | ForEach-Object {
{
$evts = Get-WinEvent -FilterHashtable #{Path=$_;id="4663"} -Oldest
foreach ($evt in $evts) {
$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\X4663Events.csv"
I have no idea, why no file is processed. The file will be created, but it is empty execpt for the headline.
It doesn't have to be that hard. Typical powershell looks more like this. Build an object, then export to csv. Know what you're doing, and verify each piece.
$evts = get-winevent security -MaxEvents 3
$objs = foreach ($evt in $evts) {
[xml]$xml = $evt.toxml()
$subjectusername = $xml.event.EventData.data |
where name -eq subjectusername |
select -expand '#text'
$subjectdomainname = $xml.event.EventData.data |
where name -eq subjectdomainname |
select -expand '#text'
[pscustomobject]#{
SubjectUserName = $subjectusername
SubjectDomainName = $subjectdomainname
}
}
$objs
$objs | export-csv mylog.csv
get-content mylog.csv
SubjectUserName SubjectDomainName
--------------- -----------------
SYSTEM NT AUTHORITY
MYCOMP$ AD
MYCOMP$ AD
#TYPE System.Management.Automation.PSCustomObject
"SubjectUserName","SubjectDomainName"
"SYSTEM","NT AUTHORITY"
"MYCOMP$","AD"
"MYCOMP$","AD"

Display output from multiple variables in a for loop

I am trying to output different attributes of a Skype response group queue for documentation purpose.
I want to get Name, TimeoutThreshold, TimeoutAction , Timeouturi, OverflowThreshold, OverflowAction , OverflowCandidate as a .csv file header in row 1 and then the output to be entered in various columns from row 2.
I have tried below, but the formatting is really bad and the headers keep repeating. Can some one please help.
Also tried getting output in HTML, but no luck.
$p = Get-CsRgsQueue | Where-Object {$_.Name -like "IPL*"} | Select-Object Name
foreach ($Name in $p)
{
$q = Get-CsRgsQueue -Name "$Name"
$N = $q.Name
$TT = $q.TimeoutThreshold
$TA = $q.TimeoutAction.Action
$TAU = $q.TimeoutAction.uri
$OF = $q.OverflowThreshold
$OFA = $q.OverflowAction
$OFC = $q.OverflowCandidate
$out = New-Object PSObject
$out | Add-Member NoteProperty QueueName $N
$out | Add-Member NoteProperty Timeout $TT
$out | Add-Member NoteProperty TimeoutAction $TA
$out | Add-Member NoteProperty TransferURI $TAU
$out | Add-Member NoteProperty OverflowThreshhold $OF
$out | Add-Member NoteProperty OverflowAction $OFA
$out | Add-Member NoteProperty OverflowCandidate $OFC
$out | FT -AutoSize | Export-Csv C:\abc.csv -Append
}
I have tried below, but the formatting is really bad and the headers
keep repeating. Can some one please help.
That's because you pipe your objects through FT -AutoSize (Format-Table -AutoSize) - only ever use the Format-* cmdlets when you're about to show/present your data.
You can also save some time by only calling Get-CsRgsQueue once, piping it to ForEach-Object and finally construct a hashtable for the object properties:
Get-CsRgsQueue | Where-Object {$_.Name -like "IPL*"} | ForEach-Object {
New-object psobject -Property #{
QueueName = $_.Name
Timeout = $_.TimoutThreshold
TimeoutAction = $_.TimeoutAction.Action
TransferURI = $_.TimeoutAction.Uri
OverflowThreshhold = $_.OverflowThreshold
OverflowAction = $_.OverflowAction
OverflowCandidate = $_.OverflowCandicate
}
} |Export-Csv c:\abc.csv -NoTypeInformation
short solution of Mathias Jessen
Get-CsRgsQueue | where Name -like "IPL*" | %{
[pscustomobject] #{
QueueName = $_.Name
Timeout = $_.TimoutThreshold
TimeoutAction = $_.TimeoutAction.Action
TransferURI = $_.TimeoutAction.Uri
OverflowThreshhold = $_.OverflowThreshold
OverflowAction = $_.OverflowAction
OverflowCandidate = $_.OverflowCandicate
}
} | Export-Csv C:\result.csv -NoType

Script output that will work on the console as well as with Export-Csv

I'm working on a basic PowerShell script that inputs a pair of dates then gets all accounts with passwords expiring between those times. I'd like to output the data to the console in a way that is compatible with Export-Csv. That way the person running the script can either just view in the console, or get a file.
Here is my script:
[CmdletBinding()]
param(
[string]$StartDate = $(throw "Enter beginning date as MM/DD/YY"),
[string]$EndDate = $(throw "Enter end date as MM/DD/YY")
)
$start = Get-Date($StartDate)
$end = Get-Date($EndDate)
$low = $start.AddDays(-150)
$high = $end.AddDays(-150)
$passusers = Get-ADUser -Filter { PasswordLastSet -gt $low -and PasswordLastSet -lt $high -and userAccountControl -ne '66048' -and userAccountControl -ne '66080' -and enabled -eq $true} -Properties PasswordLastSet,GivenName,DisplayName,mail,LastLogon | Sort-Object -Property DisplayName
$accts = #()
foreach($user in $passusers) {
$passLastSet = [string]$user.PasswordLastSet
$Expiration = (Get-Date($passLastSet)).addDays(150)
$obj = New-Object System.Object
$obj | Add-Member -MemberType NoteProperty -Name Name -Value $user.DisplayName
$obj | Add-Member -MemberType NoteProperty -Name Email -Value $user.mail
$obj | Add-Member -MemberType NoteProperty -Name Expiration -Value $expiration
$accts += $obj
}
Write-Output ($accts | Format-Table | Out-String)
This prints to the console perfectly:
Name Email Expiration
---- ----- ----------
Victor Demon demonv#nsula.edu 1/3/2016 7:16:18 AM
However when called with | Export-Csv it doesn't:
#TYPE System.String
Length
5388
I've tried multiple variations using objects, and data tables, however it seems like I can only get it to work for console or for CSV, not for both.
Replace
Write-Output ($accts | Format-Table | Out-String)
with
$accts
That way your users can run your script any way they like, e.g.
.\your_script.ps1 | Format-Table
.\your_script.ps1 | Format-List
.\your_script.ps1 | Export-Csv
.\your_script.ps1 | Out-GridView
...
Format-Table | Out-String converts your output to a single string whereas Export-Csv expects a list of objects as input (the object properties then become the columns of the CSV). If Export-Csv is fed a string, the only property is Length, so you get a CSV with one column and one record.
$accts | ConvertTo-Csv | Tee -File output.csv | ConvertFrom-Csv