A (BIG) Trick Listing Windows updates using PowerShell

If you (like me) are using Microsoft.Update.Session for listing the installed windows updates, you might be surprised about something I spent a lot of time today.
Our dream team here is deploying a very cool project for a client where we automated all the install/controlling of the windows updates in an environment. After some weeks, another script is run in another environment and gets the differences between these environments and just install in this environment those updates that are differences. It means that was tested and approved. We will blog about it.
Well, one of our functions get the installed updates in the computer passed as parameter, but in an specific server a few KB were being listed two times. It would not be weird if the UpdatedID and the RevisionNumber was not the same. How can the same update with the same KB, UPdateID and RevisionNumber installed two times ? Ha! It cannot .
First let’s take a look in a part of my code :
$session = [activator]::CreateInstance([type]::GetTypeFromProgID(“Microsoft.Update.Session”,$ComputerName))
$us = $session.CreateUpdateSearcher()
$qtd = $us.GetTotalHistoryCount()
$hot = $us.QueryHistory(0, $qtd)
foreach ($Upd in $hot) {
$OutPut = New-Object -Type PSObject -Prop @{
‘ComputerName’=$computername
‘UpdateDate’=$Upd.date
‘KB’=[regex]::match($Upd.Title,’KB(\d+)’)
‘UpdateTitle’=$Upd.title
‘UpdateDescription’=$Upd.Description
‘SupportUrl’=$Upd.SupportUrl
‘UpdateId’=$Upd.UpdateIdentity.UpdateId
‘RevisionNumber’=$Upd.UpdateIdentity.RevisionNumber
}
Write-Output $OutPut
}
and the output was :
ComputerName : DEATHSTAR
UpdateDate : 8/6/2014 2:15:36 PM
RevisionNumber : 200
SupportUrl : https://support.microsoft.com
UpdateTitle : Security Update for Windows Server 2012 R2 (KB2961072)
KB : KB2961072
UpdateDescription : A security issue has been identified in a Microsoft software product that could affect your system. You can help
protect your system by installing this update from Microsoft. For a complete listing of the issues that are included
in this update, see the associated Microsoft Knowledge Base article. After you install this update, you may have to
restart your system.
UpdateId : f9180040-e423-4fab-9a5b-78c46e9db72c
ComputerName : DEATHSTAR
UpdateDate : 8/6/2014 2:47:19 PM
RevisionNumber : 200
SupportUrl : https://support.microsoft.com
UpdateTitle : Security Update for Windows Server 2012 R2 (KB2961072)
KB : KB2961072
UpdateDescription : A security issue has been identified in a Microsoft software product that could affect your system. You can help
protect your system by installing this update from Microsoft. For a complete listing of the issues that are included
in this update, see the associated Microsoft Knowledge Base article. After you install this update, you may have to
restart your system.
UpdateId : f9180040-e423-4fab-9a5b-78c46e9db72c
As you can see the it have a difference in the time..a few minutes between them.
Well. as I am outputting a psobject in he function I decide to use the live object and changed the output ho have more data to analyse
$session = [activator]::CreateInstance([type]::GetTypeFromProgID(“Microsoft.Update.Session”,$ComputerName))
$us = $session.CreateUpdateSearcher()
$qtd = $us.GetTotalHistoryCount()
$hot = $us.QueryHistory(0, $qtd)
$hot
and then the force awakens : Take a look at the output in Bold :
Operation : 1
ResultCode : 2
HResult : 0
Date : 8/6/2014 2:15:36 PM
UpdateIdentity : System.__ComObject
Title : Security Update for Windows Server 2012 R2 (KB2961072)
Description : A security issue has been identified in a Microsoft software product that could affect your system. You can help
protect your system by installing this update from Microsoft. For a complete listing of the issues that are included
in this update, see the associated Microsoft Knowledge Base article. After you install this update, you may have to
restart your system.
UnmappedResultCode : 0
ClientApplicationID : AutomaticUpdatesWuApp
ServerSelection : 1
ServiceID :
UninstallationSteps : System.__ComObject
UninstallationNotes : This software update can be removed by selecting View installed updates in the Programs and Features Control Panel.
SupportUrl : https://support.microsoft.com
Operation : 1
ResultCode : 4
HResult : -2145099757
Date : 8/6/2014 2:47:19 PM
UpdateIdentity : System.__ComObject
Title : Security Update for Windows Server 2012 R2 (KB2961072)
Description : A security issue has been identified in a Microsoft software product that could affect your system. You can help
protect your system by installing this update from Microsoft. For a complete listing of the issues that are included
in this update, see the associated Microsoft Knowledge Base article. After you install this update, you may have to
restart your system.
UnmappedResultCode : -2145099757
ClientApplicationID : AutomaticUpdatesWuApp
ServerSelection : 1
ServiceID :
UninstallationSteps : System.__ComObject
UninstallationNotes : This software update can be removed by selecting View installed updates in the Programs and Features Control Panel.
SupportUrl : https://support.microsoft.com
Categories : System.__ComObject
Can you see the difference ? Can you feel the force ?
The second one was tried and failed to install (result code 4) The codes are :
0 = Not Started
1 = In Progress
2 = Succeeded
3 = Succeeded With Errrors
4 = Failed
5 = Aborted
It means that the Com Object also list the updates that were tried to install and failed or in any situation describe above. IF you have the same update trisd to install 6 times failed and 1 successfully it will show to you 7 times in the list.
You need to filter the resultcode to get only the successfully updates – resultcode = 2 (in my case) :
So I change my code to :
$session = [activator]::CreateInstance([type]::GetTypeFromProgID(“Microsoft.Update.Session”,$ComputerName))
$us = $session.CreateUpdateSearcher()
$qtd = $us.GetTotalHistoryCount()
$hot = $us.QueryHistory(0, $qtd)
foreach ($Upd in $hot) {
if ($Upd.operation -eq 1 -and $Upd.resultcode -eq 2) {
$OutPut = New-Object -Type PSObject -Prop @{…………………………….
Remember… If it is PowerCool, it is PowerShell!