Archive for the “Hot Fix” Category

This week I had the need to scan several systems and see which hotfixes were installed on which machines and also figure out which hotfixes I needed to install to make sure all machines were identical. Now that PowerShell V2 has been RTM’d in windows 7 and is included in the Release Candidate of the Windows Management Framework, I am going to go with V2 features. However, this script could be ported to V1 if need be.

As I was thinking about this problem, there were a few tools in the toolkit I thought I could use. The first is the new cmdlet, get-hotfix. This is just a wrapper of Win32_QuickFixEngineering but its nice to have it abstracted up to the cmdlet level. The second tool I thought of using is compare-object. I have known about this cmdlet but haven’t had a real opportunity to use it much. It’s actually very powerful but it does take a bit of neuron firing to wrap your head around how it works.

The way I set this is up allows me to compare two servers.  I also have a credential parameter that is used to access servers so I can do my part in supporting the principle of Least Privilege and not be logged in with a Domain Admin account all the time.

So I pull the list of installed hotfixes from each server and select only the HotfixId property. This will make using the compare-object cmdlet a bit easier. If we do a get-member on compare-object we see that it outputs a PSObject with 2 noteproperties, a InputObject and a SideIndicator.

image

From the help on compare-object we find this description of the SideIndicator property:

The result of the comparison indicates whether a property value appeared only in the object from the Reference set (indicated by the <= symbol), only in the object from the Difference set (indicated by the => symbol) or, if the IncludeEqual parameter is specified, in both objects (indicated by the == symbol).

Well that does the job but frankly its output is difficult to easily interpret at first glance. The beauty of PowerShell is that if you really don’t like the way something works, you can easily work around it. In this case, I created a new array of custom objects that have three properties: KB, the name of the first server, and the name of the second server. (Lines 19 and 22)

Then I foreach’d (the new verb of the day) through the collection of compared hotfixes and switched on the “SideIndicator” property. I did this to make the output more clear so users of the script would not have to interpret all the arrows and equal signs generated by compare-object.

Here is a sample of the output:

image

I used Write-Host to generate some text output but I also get back an object that I can slice and dice later on.

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
Function Compare-InstalledHotfix {
param (
[parameter(Mandatory=$true,Position=0)]
$server1,

[parameter(Mandatory=$true,Position=1)]
$server2, 

[parameter(Mandatory=$true,Position=3)]
[Management.Automation.PSCredential]
$credential
)

$server1HotFix = get-hotfix -computer $server1 -Credential $credential | select HotfixId
$server2HotFix = get-hotfix -computer $server2 -Credential $credential | select HotfixId

$comparedHotfixes = compare-object $server2HotFix $server1HotFix -IncludeEqual

$result = @();

foreach ($c in $comparedHotfixes) {
    $kbinfo = "" | select KB,$server1,$server2
    $kbinfo.KB = $c.InputObject.HotfixId
    switch ($c.SideIndicator)
    {
    "==" {
            write-host -ForegroundColor Green "Both servers have $($c.InputObject.HotfixId)"
            $kbinfo.($server1) = $true
            $kbinfo.($server2) = $true
            $result += $kbinfo
         }
        
    "=>" {
            write-host -ForegroundColor Yellow "$server1 has $($c.InputObject.HotfixId) but $server2 doesn’t"
            $kbinfo.($server1) = $true
            $kbinfo.($server2) = $false
            $result += $kbinfo
          }
         
    "<="  {
            write-host -ForegroundColor Magenta "$server2 has $($c.InputObject.HotfixId) but $server1 doesn’t"
            $kbinfo.($server1) = $false
            $kbinfo.($server2) = $true
            $result += $kbinfo
          }
    } # End Switch
  } # End foreach
   $result
 } # End Function

This code is also available on the TechNet Code Gallery and up on PoshCode

Comments 10 Comments »