Script: check-spupdates.ps1
# Script to check registry on multiple servers for Office patches and security updates) # Params # -filter : fileter on the registry lookup - normally can be ignored # -ServerListFile : File containing a list of server names to check. One line per server # -PatchListFile : List of KB patches - i.e. KB2553345 - one per line. Will return if the patch has been applied or not. If this param is not specified, all SP patches installed on the # Server will be returned. This could be used to create a ServerListFile (using just the server name field) if comparison is required for other servers. # -regpath : The root of the registry where update information is stored - can normally be ignored, as default is set for the param to the correct location # -Servers : Can be used if a ServerListFile is not used, so we can specifity the servers in the comamnd line. If neither servers or ServerListFile specified, just check local server # -all : retruns all patches within the S-1-5-18 registry, even if they may not be Office related. Param($Filter = ".*",$ServerListFile, $PatchListFile, $regpath ="SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products", $servers, [switch]$all) function Check-RegKeys { Param($regkey,$Server) $ServerKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $Server) $SubKey = $ServerKey.OpenSubKey($regkey,$false) If(!($SubKey)){Return} if ($regkey -ilike "*Patch*"){ $SubKeyValues = $SubKey.GetValueNames() if($SubKeyValues) { foreach($SubKeyValue in $SubKeyValues) { $Key = @{n="Key";e={$SubKey.Name -replace "HKEY_LOCAL_MACHINE\\",""}} $ValueName = @{n="ValueName";e={$SubKeyValue}} $Value = @{n="Value";e={$_}} $SubKey.GetValue($SubKeyValue) | ?{$_ -match $filter} | Select-Object $ValueName,$Value, @{n="path";e={$subkey.name}} } } } $SubKeyName = $SubKey.GetSubKeyNames() foreach($subkey in $SubKeyName) { $SubKeyName = "$regkey\$subkey" Check-RegKeys $SubKeyName $server } } # Get server list, depending on params - if not used, just check the local server if (!$servers){ if ($ServerListFile){ $Servers = Get-Content $ServerListFile } else{ $servers = $env:computername } } # Get Patches if ($PatchListFile){ try{$Patches = Get-Content $PatchListFile}catch {write-host " - Could not load Patch List File - will return all installed patches instead.."} $patches = $null } # Cycle through all servers foreach ($server in $Servers){ # Create array for results $allresults = @() write-host "Processing Server: $($server)" write-host " - Getting Registry" # Get the registry entries for the patches $ServerPatches = Check-RegKeys $regPath $Server write-host " - Obtained Registry" # Format the patches so we can get the relevent information $patchraw = $ServerPatches | Where-Object {$_.ValueName -ne "AllPatches"} | group Path foreach ($group in $patchraw){ # Cycle through each patch # Create object for results $results = "" | Select Server, DisplayName, KB, InstallDate, MoreInfoURL # Set data in object from the registry group $results.Server = $Server $results.DisplayName = $($group.group | Where-Object{$_.ValueName -eq "DisplayName"}).Value $results.InstallDate = ([datetime]::ParseExact($($group.group | Where-Object{$_.ValueName -eq "Installed"}).Value,”yyyyMMdd”,$null)).ToShortDateString() $results.MoreInfoURL = $($group.group | Where-Object{$_.ValueName -eq "MoreInfoURL"}).Value if ($results.DisplayName -ilike "*kb*"){ $results.KB = "KB" + ([regex]::split(($results.DisplayName).ToUpper(), 'KB'))[1].split(")")[0] } elseif($results.MoreInfoURL -ilike "*/kb/*"){ $results.KB = "KB" + (($results.MoreInfoURL).split("/"))[-1] } if ($all){ $allresults += $results } elseif (($results.MoreInfoURL).StartsWith("http://support.microsoft.com") ){ # Filter out so only relevent patches are returned $allresults += $results } } #Remove deplicates and sort in KB order $allresults = $allresults | Sort-Object -Unique * | Sort-Object KB # Patches specified, so we will test for these in the registry results if ($patches){ foreach ($patch in $Patches){ write-host " - testing patch: $patch" $patchlookup = $allresults -match $patch if (!$Patchlookup){ $patch | select @{Expression={$server};Name="Server"}, @{Expression={$patch};Name="KB"}, @{Expression={"False"};Name="Applied"} } else{ $patchlookup | select *,@{Expression={"True"};Name="Applied"} } } } else{ # No patches to test specified so retun all results $allresults } }
No comments:
Post a Comment