In the previous tip we used Get-WinEvent to read the Windows event log system and get a list of recently installed software, then used Select-Object to pick the properties that yield useful information:
Get-WinEvent -FilterHashtable @{ ProviderName="MSIInstaller"; ID=1033 } | Select-Object -Property TimeCreated, Message
Unfortunately, most of the information we are after is embedded into the “Message” property so we would have to extract it via string manipulation.
However, whenever you read event log info via Get-WinEvent, the actual event information is also available via the “Properties” property. The “Properties” property contains an array with information about the event, and this information is then embedded into the static string template found in “Message”.
All you need to know is the design of this “Properties” array. It is specific per event ID. Let’s query one event and then look at the “Properties” array – run this:
Get-WinEvent -FilterHashtable @{ ProviderName="MSIInstaller"; ID=1033 } | Select-Object -First 1 -ExpandProperty Properties
The result looks like this now:
Value ----- Elgato Stream Deck 4.9.3.13222 1033 0 Elgato Systems GmbH (NULL) {123, 49, 54, 66...}
By looking at the actual random data, for events with ID 1033 written by the provider “MSIInstaller”, the event data array is always constructed like this:
Index | Purpose |
0 | Software Name |
1 | Version |
2 | Language |
3 | Return Code |
4 | Company |
To insert any of these information items in your report, use this code:
$name = @{ Name = 'Name' Expression = { $_.Properties[0].Value } } $version = @{ Name = 'Version' Expression = { $_.Properties[1].Value -as [Version] } } $vendor = @{ Name = 'Vendor' Expression = { $_.Properties[4].Value } } $result = @{ Name = 'Result' Expression = { $_.Properties[3].Value-as [int] } } Get-WinEvent -FilterHashtable @{ ProviderName="MSIInstaller"; ID=1033 } | Select-Object -Property TimeCreated, $name, $version, $vendor
As you can see, at the top of the script a number of hash tables are defined. Their “Name” key defines the property (or “column”) name in your result, and their “Expression” key defines the code that is necessary to fill that item. $_ is one individual event log entry, so we tap into its “Properties” property, then choose the appropriate index according to our table above, and finally read its “Value” property. Optionally, you can then use the -as operator to cast the string data into a more appropriate .NET type.
All of these principles are the same for any event log entry you query using Get-WinEvent. Look at the rich and beautiful output result:
TimeCreated Name Version Vendor ----------- ---- ------- ------ 09.08.2022 00:52:43 Elgato Stream Deck 4.9.3.13222 Elgat... 15.07.2022 11:49:43 Microsoft .NET Core Host - 3.1.27 (x86) 24.108.31415 Micro... 15.07.2022 11:49:36 Microsoft .NET Core Host FX Resolver - 3.1.27 (x86) 24.108.31415 Micro... 15.07.2022 11:49:34 Microsoft .NET Core Runtime - 3.1.27 (x86) 24.108.31415 Micro... 15.07.2022 11:49:31 Microsoft Windows Desktop Runtime - 3.1.27 (x86) 24.108.31415 Micro... 15.07.2022 11:47:28 Elgato Stream Deck 4.9.3.13222 Elgat... 15.07.2022 11:44:57 Microsoft ASP.NET Core 3.1.27 Shared Framework (x86) 3.1.27.22316 Micro... 15.07.2022 10:09:43 Microsoft ASP.NET Core 3.1.27 Shared Framework (x64) 3.1.27.22316 Micro... 15.07.2022 10:09:40 Microsoft .NET Core Toolset 3.1.421 (x64) 12.21.32439 Micro... 15.07.2022 10:08:55 Microsoft .NET Core 3.1 Templates 3.1.421 (x64) 3.1.28.16055 Micro... 15.07.2022 10:08:54 Microsoft Windows Desktop Runtime - 3.1.27 (x64) 24.108.31415 Micro... ...