Question

I am trying to write a PowerShell script that will query all the servers in Active Directory and see the last date a Windows Update was applied.

I was having some trouble, so just to get it done, I created two scripts, one in Powershell to get the servers and the other in VBScript to query the last date. I found a this Powershell module that allows me to query the last install date, but it is extremely slow, especially on remote servers.

Here is the PS code:

Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' -Properties * |
Select-Object Name | Sort-Object Name |
ForEach-Object {
    Get-WUHistory -ComputerName $_.Name | Sort-Object Date,ComputerName -Descending |
    Select-Object -First 1
}

Its so slow, its practically unusable.

I have some VBScript which I cobbled together that is much faster. See below:

On Error Resume Next
Set fso = CreateObject("Scripting.FileSystemObject")
Set file = fso.OpenTextFile ("servers.csv", 1)
server = ""

Do Until file.AtEndOfStream
  line = file.Readline
  server = line
  'wscript.echo server
  Set objSession = CreateObject("Microsoft.Update.Session", server)
  If Err.Number <> 0 Then
    'WScript.Echo server & " Error: " & Err.Number & " Error (Hex): " & Hex(Err.Number) & " Source: " &  Err.Source & " Description: " &  Err.Description
    WScript.Echo server & " Communications Error"
    Err.Clear
  Else
      Set objSearcher = objSession.CreateUpdateSearcher
      Set colHistory = objSearcher.QueryHistory(1, 1)
      For Each objEntry in colHistory
        Wscript.Echo server & " " & objEntry.Date
      Next
  End If
Loop

file.Close

Is there an easy way to get the speed of the VBScript into the Powershell code?


Here is the working Powershell code (modified again) if anyone is interested:

$ErrorActionPreference= 'silentlycontinue'
Get-ADComputer -Filter 'OperatingSystem -like "*Server*"' -Properties * | Select-Object Name |
ForEach-Object {
    If (Test-Connection $_.Name -Count 1){
        Get-HotFix -ComputerName $_.Name | Sort-Object InstalledOn -Descending | Select-Object -First 1 
    }
    else {
        Write-host $_.Name " Connection Error"
    }
} |
Sort-Object InstalledOn
Was it helpful?

Solution

Does Get-HotFix meet your needs?

Get-HotFix -ComputerName $_.Name | Measure-Object InstalledOn -Maximum

Your performance issues could be coming from Get-ADComputer. I'd do some troubleshooting to see which piece is causing you problems.

OTHER TIPS

Tim Ferrill already provided you the answer but for the record you could have done something like this

$ScriptBlock = {
    $hash=@{}
    $Session = New-Object -ComObject Microsoft.Update.Session
    $Searcher = $Session.CreateUpdateSearcher()
    $hash[$env:Computername] = $Searcher.QueryHistory(1,1) | select -ExpandProperty Date
    $hash
}

Invoke-Command -ComputerName $serverlist -ScriptBlock $ScriptBlock

This would get you something like

Name                    Value
----                    -----
Server1                 5/16/2014 2:11:42 PM
Server2                 4/14/2014 1:55:03 PM
Server3                 5/6/2014 5:36:51 PM
(get-hotfix -computername SERVERNAME | sort installedon)[-1] >> c:\file.txt

This will get you the last installed date. I just use some excel work to clean up the output after you run it against all your server names.

Got that command from "get-help get-hotfix -full"

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top