If you are looking for stability on some servers and unexpected, and sometimes changes seem to happen, however, however what I seem to be lacking is evidence of what changed on what day, or more accurately what has been changed in the time the event log has data in it.
When a server or an application provided by a server starts failing you have a problem, and it would be nice to know exactly what has changed all day, but not necessarily by who because that information is not usually locked for many events.
I therefore thought the first time the script is run it could create a baseline, and then future runs of the script would tell you any hardware or software changes that are successfully written to the event log, this means hardware changes will be captured and so will any MSI installer based products as that writes to the eventlog.
The majority of the Microsoft product range will use MSI installer or even for the new applications, MSIX - if this is the case, this script will capture the date and time it was removed and the name of the software.
One of the most common questions I usually find myself being asked is what has changed?
Unfortunately, without evidence was falling through the event that question is the same as asking someone how long is the piece of string, So rather than manually go through the event log, I thought I’d write to script to do exactly this.
The script or take a list of servers in text file and remote scan the application and system log for relevant event, IDs and display them both on the screen and in a CSV file.
The Script : DeviceChanges.ps1
# Read list of target servers from Target.txt file
$targetServers = Get-Content -Path "Target.txt"
# Define the event log sources
$eventLogSources = @("System", "Application")
# Define the events to track (hardware changes, software installations, and uninstalls)
$events = @(7, 22, 437, 438, 439, 11707, 11724)
# Define output CSV file path
$outputCSV = "SoftwareAudit.csv"
# Check if baseline data exists
if (Test-Path $outputCSV) {
# Load baseline data
$baselineData = Import-Csv -Path $outputCSV
} else {
# Create an empty array for baseline data if file doesn't exist
$baselineData = @()
}
# Create an empty array to store event data
$allEventData = @()
# Loop through each target server
foreach ($server in $targetServers) {
Write-Host "Scanning $server..."
Get events from the event logs of the current server
$eventLogEntries = Invoke-Command -ComputerName $server -ScriptBlock {
Get-WinEvent -LogName $using:eventLogSources -MaxEvents 1000 | Where-Object {$using:events -contains $_.Id}
}
# Loop through each event log entry
foreach ($entry in $eventLogEntries) {
$eventInfo = [PSCustomObject]@{
Server = $server
DateTime = $entry.TimeCreated.ToLocalTime() # Get local time of the event
EventID = $entry.Id
Source = $entry.LogName
Message = $entry.Message
}
$allEventData += $eventInfo
}
Write-Host "Scan of $server complete."
}
# Compare with baseline and identify changes
$changes = Compare-Object -ReferenceObject $baselineData -DifferenceObject $allEventData -Property Server, DateTime, EventID, Source, Message -PassThru
# Export all event data to CSV file
$allEventData | Export-Csv -Path $outputCSV -NoTypeInformation
Write-Host "Hardware, software installations, and uninstalls tracked across all servers. Output saved to $outputCSV"
# Output changes
if ($changes) {
Write-Host "Changes detected:"
$changes | Format-Table -AutoSize
} else {
Write-Host "No changes detected."
}