I have a script which returns me user name, date , logon type and message from the security log with event ids 4624 and 4634 with logon type 2.
the problem is that it returns me only a part of the username. E.g. if the username is aaaa.bbbb it returns only aaaa. if the user name is cccc it returns cccc. How can i get the entire username please?
$content = $i.message| Find-Matches -Pattern “Kontoname:\s+\w+”
if($content.Count -eq 2) {$account = $content[1]} else {$account = $content}
$account = (($account -split “:”)[1]) -replace “\s+”,”"`
I don't have any example data to work with for events 4623 and 4634, but I've found the 'Properties' property or 'ToXML' method from the resulting System.Diagnostics.Eventing.Reader.EventLogRecord to be quite helpful. Much more helpful than trying to manually parse the 'Message' content.
Try this
#Get an example event to work with
$EventExample = Get-WinEvent <#your params here#> | Select -first 1
#Using properties property
#This will list some data you can access through the properties member
#From here, just figure out which array index you need
$EventExample.Properties
#Using ToXML method
#This will list the same data as properties...
#With a Name (key) and a #text (value) that you can use to help identify the data
$EventXML = [xml]$EventExample.ToXML()
$EventXML.event.eventdata.data
Here is a lengthy writeup on pulling this event data from Ashley McGlone.
Good luck!
Related
I am new to this Powershell.
I am trying to learn how to modified output.
When I run "Write-output $result | format-list" I have the following output
userDetails : #{id=AA:BB:CC:DD:11:22; connectionStatus=CONNECTED; hostType=WIRELESS;
authType=WPA2/WPA3+802.1x/FT-802.1x}
connectedDevice : {#{deviceDetails=}}
How do I rewrite this output to below using powershell 7.2 ? I would like to have
userDetails :
connectionStatus= CONNECTED
hostType = WIRELESS
authType = WPA2/WPA3+802.1x/FT-802.1x
connectedDevice :
Thank you for your help.
Note: I'm assuming that you're looking for a friendlier display representation of your data. For programmatic processing, Format-* cmdlets should be avoided, for the reasons explained in this answer.
What you're looking for is for Format-List to work recursively, i.e. to not only list the individual properties and their values for each input object itself, but also for nested objects contained in property values.
Format-List does not support this:
Nested objects are represented by their single-line .ToString() representations.
If they're part of a collection (enumerable), the individual elements' representations are joined with , on a single line, and are enclosed in {...}(!) as a whole. How many elements are shown at most is controlled by the $FormatEnumerationLimit preference variable, which defaults to 4.
However, you can approximate recursive listing behavior with Format-Custom; using a simplified example:
# Nested sample object to format.
[pscustomobject]#{
userDetails = [pscustomobject] #{
id = 'AA:BB:CC:DD:11:22'
connectionStatus= 'CONNECTED'
hostType = 'WIRELESS'
authType = 'WPA2/WPA3+802.1x/FT-802.1x'
}
connectedDevice = '...'
} |
Format-Custom -Depth 1 # use higher -Depth levels for multi-level expansion
Output:
class PSCustomObject
{
userDetails =
[
class PSCustomObject
{
id = AA:BB:CC:DD:11:22
connectionStatus = CONNECTED
hostType = WIRELESS
authType = WPA2/WPA3+802.1x/FT-802.1x
}
]
connectedDevice = ...
}
Note:
Caveat: If a custom view happens to be defined for a given input object's type via associated formatting data, it is that custom view that Format-Custom will invoke, not the structural representation shown above; however, this is rare ([datetime] is a rare example).
Apart from the output showing the structure recursively, the format differs from that of Format-List as follows:
Complex objects are enclosed in class <typeName> { ... }
Elements of collections (enumerables) each render on their own (group of) line(s), enclosed in [ ... ] overall. However, as with Format-List, the number of elements that are shown at most is limited by $FormatEnumerationLimit.
To prevent excessively nested output, Format-Custom stops recursing at a depth of 5 by default; you can control the recursion depth via the -Depth parameter, 1 meaning that only objects in immediate child properties are expanded.
When the recursion depth limit is reached, non-collection objects are represented by their .ToString() representations, as with Format-List.
Here is some code that produces output close to your desired output:
# Create sample data
$result = [pscustomobject] #{
userDetails = [pscustomobject]#{ id="AA:BB:CC:DD:11:22"; connectionStatus="CONNECTED"; hostType="WIRELESS"; authType="WPA2/WPA3+802.1x/FT-802.1x"}
connectedDevice = [pscustomobject]#{ deviceDetails=$null }
}
# Produce output
"userDetails :"
($result.userDetails |
Format-List -Property connectionStatus, hostType, authType |
Out-String).Trim() -replace '(?m)(?<=^[^:]+):', '='
"`nconnectedDevice :"
# TODO: add similar code as for .userDetails
Output:
userDetails :
connectionStatus = CONNECTED
hostType = WIRELESS
authType = WPA2/WPA3+802.1x/FT-802.1x
connectedDevice :
Using member access .userDetails to select a child object (similar to Select-Object -ExpandProperty userDetails).
Using Format-List -Property to output a list of the given properties
Using Out-String to create a string from the formatting data that is produced by Format-List. This string looks exactly like the output you normally see on the console.
Use String method .Trim() to remove whitespace (in this case newlines) from the beginning and end.
Use the -replace operator to replace the first : of each line by =. See this regex101 demo for more information.
Below is a snip of my powershell code where my response or my variable($witrevisions) is of type array. I am looking to bind this in a html tag which i have defined in the power shell. As I am very new to coding stuff , I am looking the ways how can I bind array to html tag in best possible way
...continuing my line of code
$response4s = (Invoke-RestMethod -Uri $uriAccount -Method get -Headers $AzureDevOpsAuthenicationHeader).values
$wits = $response4s | where({$_.fields.'System.WorkItemType' -eq 'Task'}) # Only retrieve Tasks
$witrevisions = #()
foreach($wit in $response4s){
$customObject = new-object PSObject -property #{
"Title" = $wit.fields.'System.Title'
"AssignedTo" = $wit.fields.'System.AssignedTo'
}
$witrevisions += $customObject
}
$witrevisions | Select-Object `
Title,
AssignedTo
}
and this the sample response i am getting in $witrevisions which i have exported in text file. its a table with two column one having emails and other having a title name.i have tried to show by giving it a table view for better understanding
Assigned To Title
xyz#outlook.com testingpro
drdr#outlook.com resttesting
and here is the html tag where I trying to bind the $witrevisions.
$DOWNLOAD_PAGE_BODY_CONTENT = "<!DOCTYPE html>
`n<html>
`n<head>
`n <title>Validation</title>
`n</head>
`n<body>
`n
`n<p>Please click the link to download the release.</p>
`n<p></p>
`n<p></p>
`n<p>$witrevisions</p>
`n</body>
`n</html>
`n"
Can someone please tell me how should I do this??
Here is an example of some code that would take your array and emit a table, with an explanation to help you tweak to your specific needs:
"<table><body>$($witrevisions|% {"<tr><td>$($_.Title)</td><td>$($_.AssignedTo)</td></tr>"} )</body></table>"
The double quotes are important because they allow string interpolation (it will replace variables with this value, versus being read a plain text. E.g. '[' + $test + ']' => "[$test]"
If you need to do more complex logic in string interpolation, you can use $(...), the ellipses being regular code.
You can iterate through an array by piping to the ForEach-Object, or it's alias %. All the code in the braces will be executed for each item in the array. The current items is represented by $_.
We're then back to string interpolation and using $(...), which is needed to access the members of the current item.
Note: There are several other ways to accomplish (functionally) the same thing. E.g. foreach(...){} vs |%{...}, so feel free to use a different technique if you are more comfortable with doing something a different way.
I am looking up data and then want to add that to some kind of list which I can reference, for example if my data looked like this:
Name - John
Last Name - Doe
Age - 55
I would want to store that in a list and be able to do foreach $member in $myList and be able to print $member.Name
Hope that makes sense, not sure what the best way to do this is, would it be creating an object? or using a hashtable?
You can use a PowerShell Hashtable for this:
$NameObject= #{
'Name'='John'
'LastName'='Doe'
'Age'='55'
}
You can do this inside of a loop to add your data like so, to create a PowerShell Object.
$NameObjectCollection = foreach($Object in $MyData)
{
#Add Data to Object
[PSCustomObject] $NameObject= #{
'Name'=$Object.Property1
'LastName'=$Object.Property2
'Age'=$Object.Property3
}
#Output object
$NameObject
}
#Now you can loop over this data
foreach($NameObject in $NameObjectCollection)
{
#Access the properties of the NameObject`
$NameObject.Name
$NameObject.LastName
$NameObject.Age
}
I have and existing PowerShell script (not written by me!) which is designed to use a passed-in parameter (SCOM Alert ID) to then set additional information in the alert, e.g. $alert.CustomField1 = $alert.PrincipleName etc etc.
I am looking to add functionality to this script to be able to add additional 'custom' information which is stored in a separate text/CSV file. The text/CSV file has header line
ServerName,ServiceOwner,Application Tier
so a row in the file would be
MYSERVER.CONTOSO.COM,Joe Bloggs, Tier 1
There will be one unique row for each server in our environment (over 600 rows).
So what I need to do is using the passed-in alert ID. I can use $alert.PrincipleName to find the corresponding row in the text file and pull in the additional details stored in field 2 and 3, i.e. ServiceOwner and ApplicationTier.
This logic holds for the majority of alerts but IF server name is a specific value (e.g. MYSTSERVER.CONTOSO.COM) then instead of using $alert.PrincipleName to match servername in text file, I need to match on another alert property $alert.MonitoringObjectDisplayName. However, the server name in this field is part of a larger string in the format, e.g. User Services Watcher for Pool [MYTARGETSERVER.CONTOSO.COM] - so I need to extract the severname from between the square brackets of the string to then perform the match with the text file.
Hopefully I have explained what I'm trying to do clearly - if not I'm happy to provide further clarification and can also post up the existing PS Script I'm trying to modify if thats any help.
You can react to the server name like this:
$csv = Import-Csv 'C:\path\to\your.csv'
...
if ( $alert.PrincipalName -eq 'MYSTSERVER.CONTOSO.COM' ) {
if ( $alert.MonitoringObjectDisplayName -match '.*\[(.*?)\]' ) {
$targetserver = $matches[1]
}
} else {
$targetserver = $alert.PrincipalName
}
$newdata = $csv | ? { $_.ServerName -eq $targetserver } `
| select ServiceOwner, 'Application Tier'
...
$alert.CustomField2 = $newdata.ServiceOwner
$alert.CustomField3 = $newdata.'Application Tier'
...
I'm trying to pass an array of custom objects to a function for further processing of these objects.
Here's the function where I create my custom object array:
Function GetNetworkAdapterList
{
# Get a list of available Adapters
$hnet = New-Object -ComObject HNetCfg.HNetShare
$netAdapters = #()
foreach ($i in $hnet.EnumEveryConnection)
{
$netconprop = $hnet.NetConnectionProps($i)
$inetconf = $hnet.INetSharingConfigurationForINetConnection($i)
$netAdapters += New-Object PsObject -Property #{
Index = $index
Guid = $netconprop.Guid
Name = $netconprop.Name
DeviceName = $netconprop.DeviceName
Status = $netconprop.Status
MediaType = $netconprop.MediaType
Characteristics = $netconprop.Characteristics
SharingEnabled = $inetconf.SharingEnabled
SharingConnectionType = $inetconf.SharingConnectionType
InternetFirewallEnabled = $inetconf.InternetFirewallEnabled
SharingConfigurationObject = $inetconf
}
$index++
}
return $netAdapters
}
Then in my main code I call above function like this:
$netAdapterList = GetNetworkAdapterList
The $netAdapterList returns the expected data, and I can do stuff like:
$netAdapterList | fl Name, DeviceName, Guid, SharingEnabled
So far so good.
Now I want to call a function passing in the $netAdapterList
I've created a dummy function like this:
Function ShowAdapters($netAdapterListParam)
{
$netAdapterListParam | fl Name, DeviceName, Guid, SharingEnabled
}
And when I invoke it like this:
ShowAdapters $netAdapterList
Nothing gets printed out.
I've tried changing the function's signature but still no luck:
Function ShowAdapters([Object[]]$netAdapterListParam)
Function ShowAdapters([Object]$netAdapterListParam)
Function ShowAdapters([PSObject[]]$netAdapterListParam)
Function ShowAdapters([array]$netAdapterListParam)
Anybody knows what I'm doing wrong? How can I get to my custom objects inside the function?
Thanks for your reply #Christian. Tried your steps, copy pasting bits and pieces into the shell and it indeed worked. However If i run the full .ps1 script is not printing out anything.
I've run the script in Powershell IDE setting breakpoints inside the ShowAdapters function, and $netAdapterListParam has indeed the expected custom objects array I'm passing in, so I've narrowed down the issue to be in the FL commandlet.
For some reason $netAdapterList | fl Name, DeviceName, Guid, SharingEnabled did not work for me, so I ended up using the following instead:
$formatted = $netAdapterListParam | fl Name, DeviceName, Guid, SharingEnabled | Out-String
Write-Host $formatted
That did the trick and the 4 properties were printed on the screen.
Lessons learned:
1) The Powershell IDE built into Win7 can be a very useful tool for debugging scripts
2) Format-List can be quirky when formatting custom objects, so Out-String was required.