I’ve recently been asked to assist with troubleshooting an issue where remote users who VPN into the network remotely while working from home were not receiving an agent that is installed through Group Policy. Upon troubleshooting with a remote worker’s laptop, I realized that Group Policy had not been refreshed for over a month and simply executing a GPUpdate automatically installed the application. The client wanted to determine which remote devices did not have the application then proceed to run GPUpdate on them to install the application.
Many administrators will likely be familiar with the Group Policy Update… feature in the Group Policy Management Console, which automatically reaches out to all of the devices in the OU to initiate a Group Policy Update:
While this allowed us to force a GPUpdate on devices with ease, this did not provide a report on which device had the software so what I ended up doing was write a PowerShell script to accomplish this. The script reads a text file with a list of names separated by line breaks, attempts to ping the device and if it is reachable, it will attempt to determine whether it has the agent installed and if it isn’t, it would initiate a GPUpdate remotely. The result of whether it was reachable via PING, had the application installed, did not have the application installed, and not responding to the command to determine the application installed status would be written to a CSV file.
The script is provided below with the following parameters that can be adjusted:
$InventoryList > specify the text file containing the device names
$Software > Specify part of the name of the application that is being determined whether it is installed (in this example, it is anything with the word “Omni”)
Customize the $Output and Write-Host lines as required.
Note that the Invoke-GPUpdate PowerShell cmdlet will present a command prompt to the console of the remote device to initiate the GPUpdate.
The script:
$Output=@()
$InventoryList = Get-Content “C:tempInventoryList.txt”
$Software = “*Omni*”
ForEach ($Machine in $InventoryList -ne ”){
#Ping each machine found in text file
if (!(test-Connection -ComputerName $Machine -BufferSize 16 -Count 1 -ea 0 -Quiet))
{
$Output+= “$Machine,not reachable”
Write-Host “$Machine,not reachable” -ForegroundColor Red
}
Else
{
#Machine is reachable via Ping
#Checks installed programs for products that contain Omni in the name
Try {
$installed = Get-WmiObject -ComputerName $Machine -Class Win32_Product -ErrorAction Stop | sort-object Name |
Select-Object Name | Where-Object { $_.Name -like $Software}
If($installed) {
$Output+= “$Machine,Omni Installed”
Write-Host “$Machine,Omni Installed” -ForegroundColor Green
} else {
$Output+= “$Machine,Omni Not Installed”
Write-Host “$Machine,Omni Not Installed” -ForegroundColor Red
Invoke-GPUpdate -Computer $Machine -RandomDelayInMinutes 0}
# Write-Host “Invoting GPUpdate on $Machine” -ForegroundColor Red}
#EndofElse
}
Catch {
$Output+= “$Machine,Unable to check apps”
Write-Host “$Machine,Unable to check apps” -ForegroundColor Red
}
#EndofForEach
$Output | Out-file “InstalledSoftwareResult.csv”
}
}
Feel free to modify the script as needed for any purpose.