Hello,
im trying to collect some infos about pending Windows updates deployed by SCCM on our Servers. The embedded PRTG Windows Update Sensor wont work i think because of Win SCCM. Now im trying to collect the informations via WMI / Powershell. This worked fine but the only thing i can really collect is the amount of Updates without any information about the pending updates. Is there any possilbe option to show a list of Text in the Sensor? something like:
KB123456
KB123457
KB123458
etc..
Thanks in advance for your Help
Björn Bechtold
Article Comments
Hello Erhard,
Thank you for your reply. When i run this query at one of my Hosts i get the following:
IsInstalled MsrcSeverity ----------- ------------ False PS C:\> $searcher CanAutomaticallyUpgradeService : False ClientApplicationID : IncludePotentiallySupersededUpdates : False ServerSelection : 0 Online : True ServiceID : 00000000-0000-0000-0000-000000000000 IgnoreDownloadPriority : False SearchScope : 0 PS C:\>
I think that's because we use SCCM. The ordinary "Windows Update" from System Control, does not work at our enviroment, respectively dont show anything.
For this reason i used the Powershell XML Sensor to collect the Data from the SCCM Client on the destination Machine. everything works great. But i would like to provide a list of pending Updates or their descriptions.
Here is my Powershell Script to collect the data.
## übergebene Parameter definieren param( [String]$computer="localhost" ) ## definition von Variablen ## Ausstehender Boot fuer Updates (id 8) $count_boot_pending=0 ## Updates die noch installiert werden muessen (id 6) $count_Updates_to_install=0 ## Updates die fehlgeschlagen sind (id 13) $count_Updates_error=0 ## Updates installing (id 7) $count_Updates_installing=0 ## Updates Downloading (id 5) $count_Updates_downloading=0 ## Updates sonstige (rest der ids) $count_Updates_unknown_state=0 ## Variable updates mit Daten aus dem Zielsystem fuellen $updates = get-wmiobject CCM_SoftwareUpdate -namespace "ROOT\ccm\ClientSDK" -ComputerName $computer ## Update Zustände Analysieren ForEach($var in $updates){ if($var.EvaluationState -eq 8 ){ $count_boot_pending=$count_boot_pending+1 } elseif($var.EvaluationState -eq 6 ){ $count_Updates_to_install=$count_Updates_to_install+1 } elseif($var.EvaluationState -eq 13 ){ $count_Updates_error=$count_Updates_error+1 } elseif($var.EvaluationState -eq 7 ){ $count_Updates_installing=$count_Updates_installing+1 } elseif($var.EvaluationState -eq 4 ){ $count_Updates_downloading=$count_Updates_downloading+1 } else{ $count_Updates_unknown_state=$count_Updates_unknown_state+1 } } ## XML Output fuer PRTG zusammenbauen Write-Host "<?xml version=`"1.0`" encoding=`"Windows-1252`" ?>" Write-Host "<prtg>" Write-Host "<result>" Write-Host "<channel> Updates Pending </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $updates.count "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> Boot Pending </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_boot_pending "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> wait for install </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_to_install "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> Error </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_error "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> currently installing </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_installing "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> downloading </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_downloading "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> unknown state </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_unknown_state "</value>" Write-Host "</result>" Write-Host "</prtg>"
Actually im searching for an possability to show a List of Strings in the Sensor.
Kind regards.
Björn
Mar, 2017 - Permalink
Hi Björn,
Since channels can only work with numeric values, your best chance would be to pass the information into the sensor's message by using the <text>.......</text> The text block needs to be outside the <result></result> blocks and you can only have one textoutput, otherwise each following <text> would overwrite the last message. See also Setup | PRTG API | Custom Sensors in your PRTG installation.
Kind regards,
Erhard
Apr, 2017 - Permalink
Hi Erhard,
Thank you very much. Your hint helped me and i was able to provide the pending Update Names ( KBxxxxx ) in the Sensors Message Box. Works great.
Thanks Björn
Apr, 2017 - Permalink
Hi Björn,
Great, you're welcome. Feel free to share the final script here, others might find it also useful :)
Kind regards,
Erhard
Apr, 2017 - Permalink
Hi Erhard,
here is the script which collect Infos via Powershell about the Windows Updates distributed by SCCM.
The Script needs the following options set under Settings.
hand over the Hostname:
Parameter: -computer %host
run the Powershell Script in user security context with an User which has the required rights.
Security context: Use the access data for Windows on the parent device
Important on the PRTG Node:
If you want to run the Powershell Script without digital signature you had to allow this on the PRTG Node unter windows Powershell. To allow run all Powershell Scripts on the Host open an Powershell and execute the following command:
- Set-ExecutionPolicy unrestricted
## define passed parameters param( [String]$computer="localhost" ) ## definition of variables ## Pending Boot for Updates (id 8) $count_boot_pending=0 ## Updates still to be installed (id 6) $count_Updates_to_install=0 ## Updates that failed (id 13) $count_Updates_error=0 ## Updates installing (id 7) $count_Updates_installing=0 ## Updates downloading (id 5) $count_Updates_downloading=0 ## Updates other (rest of the ids) $count_Updates_unknown_state=0 ## Update name or KB article $update_KB_ids = "Server Up To Date" ## Load variable updates with data from the target system $updates = get-wmiobject CCM_SoftwareUpdate -namespace "ROOT\ccm\ClientSDK" -ComputerName $computer ## Analyze update states and write to Variables ForEach($var in $updates){ if($var.EvaluationState -eq 8 ){ $count_boot_pending=$count_boot_pending+1 } elseif($var.EvaluationState -eq 6 ){ $count_Updates_to_install=$count_Updates_to_install+1 } elseif($var.EvaluationState -eq 13 ){ $count_Updates_error=$count_Updates_error+1 } elseif($var.EvaluationState -eq 7 ){ $count_Updates_installing=$count_Updates_installing+1 } elseif($var.EvaluationState -eq 4 ){ $count_Updates_downloading=$count_Updates_downloading+1 } else{ $count_Updates_unknown_state=$count_Updates_unknown_state+1 } if ($update_KB_ids -eq "Server Up To Date"){ $update_KB_ids = "Pending Updates: KB" + $var.ArticleID } else{ $update_KB_ids += " / KB" + $var.ArticleID } } ## create XML output for PRTG Write-Host "<?xml version=`"1.0`" encoding=`"Windows-1252`" ?>" Write-Host "<prtg>" Write-Host "<result>" Write-Host "<channel> Updates Pending </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $updates.count "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> Boot Pending </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_boot_pending "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> wait for install </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_to_install "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> Error </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_error "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> currently installing </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_installing "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> downloading </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_downloading "</value>" Write-Host "</result>" Write-Host "<result>" Write-Host "<channel> unknown state </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_Updates_unknown_state "</value>" Write-Host "</result>" Write-Host "<text>" write-host $update_KB_ids Write-Host "</text>" Write-Host "</prtg>" <# CCM_SoftwareUpdate reference https://msdn.microsoft.com/en-us/library/jj155450.aspx Value State 0 ciJobStateNone 1 ciJobStateAvailable 2 ciJobStateSubmitted 3 ciJobStateDetecting 4 ciJobStatePreDownload 5 ciJobStateDownloading 6 ciJobStateWaitInstall 7 ciJobStateInstalling 8 ciJobStatePendingSoftReboot 9 ciJobStatePendingHardReboot 10 ciJobStateWaitReboot 11 ciJobStateVerifying 12 ciJobStateInstallComplete 13 ciJobStateError 14 ciJobStateWaitServiceWindow 15 ciJobStateWaitUserLogon 16 ciJobStateWaitUserLogoff 17 ciJobStateWaitJobUserLogon 18 ciJobStateWaitUserReconnect 19 ciJobStatePendingUserLogoff 20 ciJobStatePendingUpdate 21 ciJobStateWaitingRetry 22 ciJobStateWaitPresModeOff 23 ciJobStateWaitForOrchestration #>
copy this Code to an File and save it under ..\PRTG Network Monitor\Custom Sensors\EXEXML\ e.g. custom_SCCM.ps1
Now the script ( Filname ) could be selected when you create a new xmlEXESensor. Do not forget to enter the parameters from above.
Screenshots
I hope that is useful for someone.
Kind Regards
Björn
Apr, 2017 - Permalink
Thanks greatly Björn!
One minor addition I might suggest to the script - if you include LimitMode/LimitMaxWarning/LimitMinWarning tags in the XML result, when you add the sensor to PRTG it will configure those limits for you automatically.
For example, if you change the Boot Pending output as follows:-
Write-Host "<result>" Write-Host "<channel> Boot Pending </channel>" write-host "<unit> Quantity </unit>" Write-Host "<value>" $count_boot_pending "</value>" Write-Host "<LimitMode>1</LimitMode>" Write-Host "<LimitMaxWarning>0</LimitMaxWarning>" Write-Host "<LimitMaxError>1</LimitMaxWarning>" Write-Host "</result>"
...the sensor will be set up to automatically generate a warning if 1 update requires a reboot or an error if 2 or more updates require a reboot.
Again though, thanks - this will be very useful for me.
Apr, 2018 - Permalink
Hi there,
Thank you as well for the addition to the above script, rhil_wcc. :)
Best regards
Apr, 2018 - Permalink
Hi rhil_wcc,
thank you for your Reply. we're Monitoring almost 300 Servers and much more stuff ( 4000 Sensors ) and some of them are a little difficult to reboot so we had to arrane with staff maintenance windows.
i've made some Maps for SCCM Admins to check for Servers with most Updates pending so that the PRTG only Shows Critical Warnings and failures which affects our business.
Certainly it helps some other guys so they must not configure all thresholds by hand.
One additional info. It only work for these devices where the PRTG Service User has privilliges to. If i could find some time i will edit the Script so that it is possible to get the Users and credentials defined in PRTG. But it will take some time. :-)
Kind regards Björn
Apr, 2018 - Permalink
Hello Björn,
Which query are you using to retrieve the information? Does the result contain also the KB items? Regarding the built-in update sensor in PRTG, it uses this query:
$searcher = (New-Object -ComObject Microsoft.Update.Session).CreateUpdateSearcher();$searcher.Search("Type='Software'").Updates | Sort-Object -Property Dates -Descending | ft -autosize IsInstalled, MsrcSeverity
Though it's not the only query and there's further processing to divert the readings into their appropriate channels, but this particular query is the "main query". Run it locally on one of your hosts and see what you get. When using it with PRTG however, the sensor only works within domains as it relies on mutual authentication in Powershell.
Kind regards,
Erhard
Mar, 2017 - Permalink