Is it possible to treat 'Programs and Features' as event-based system and listen to changes? For example, I want to "listen" to a particular application, e.g. Notepad++, and its version is set to be x.x.x. However, as soon as this Notepad++'s version changes to y.y.y (such as being updated), I want to be notified of the change. I know that I can use PowerShell to get the currently installed applications alongside their versions, but it would be ideal to be able to "act" as soon as there is a change, rather than periodically scanning the apps and check if there are any changes.
1 Answer
Periodic scanning is technically your best option - Some software doesn't "install" at all. For that kind of thing, use one of the many inventory management softwares available.
Windows does keep track of software installation/uninstallation events using the MsiInstaller (I find most software is either already an MSI, often just wrapped by an exe).
You can get these events through Powershell, and it's much faster than scanning through the filesystem. You can also create alerts from certain event logs if that's what you're looking for:
$MsiEvents = Get-WinEvent -Computername RemoteServer -LogName Application -MaxEvents 5 -FilterXPath @'
<QueryList>
<Query Id="0" Path="Application">
<Select Path="Application">
*[System[Provider[@Name='MsiInstaller'] and
( (EventID >= 1033 and EventID <= 1036) )]]
</Select>
</Query>
</QueryList>
'@
# Format as xml to use named eventData properties
# you can filter on these - otherwise you only get the whole event text
[xml[]]$xml=$MsiEvents|Foreach{$_.ToXml()}
# Generate usable field names from xml
$report = $xml.Event | Select @{l='ID';e={$_.System.EventID.'#text'}},
@{l='TimeCreated';e={$_.System.TimeCreated.systemTime | get-date -f 'yyyy-MM-dd HH:mm:ss'}},
@{l='Name';e={
Switch ($_.System.EventID.'#text') {
1033 {'Install'}
1034 {'Uninstall'}
1035 {'Reconfigure'}
1036 {'Update'}}}},
@{l='Version';e={$_.EventData.Data[1]}},
@{l='Vendor';e={$_.EventData.Data[4]}},
@{l='Product';e={$_.EventData.Data[0]}}
$report | FT
This generates a reasonable report you can use to see which events you want to monitor:
ID TimeCreated Name Version Vendor Product
-- ----------- ---- ------- ------ -------
1035 2021-06-10 18:11:59 Reconfigure 21.005.20048 Adobe Systems Incorporated Adobe Acrobat Reader DC
1036 2021-06-10 18:11:59 Update 21.005.20048 0 Adobe Acrobat Reader DC
1033 2021-06-09 11:31:06 Install 4.10.00093 Cisco Systems, Inc. Cisco AnyConnect Diagnostics and Re...
1033 2021-05-28 12:13:23 Install 16.0.14026.20246 Microsoft Corporation Office 16 Click-to-Run Licensing Co...
1034 2021-05-28 12:13:11 Uninstall 16.0.13929.20386 Microsoft Corporation Office 16 Click-to-Run Licensing Co...
You can create a task in task scheduler to do something like send an email or run a script that is triggered by a specific event. The easiest way to do this is right-click an event in the event viewer > Attach task to this event.
Alternatively, you could adapt this script to send you an email if certain software got updated etc, and use a scheduled task to run this daily/hourly instead for example.