1

The script runs correctly when outside of Start-Job but when in a scriptblock I get incorrect results. Where am I going wrong?

I need the Start-Job functionality since I have servers where the remote commands will hang (separate problem - WMI is borked) and I need to timeout and move to the next server.

I've tried every variation I can find in Google and still don't have the results I'm looking for.

I am really at my wits end with this as I don't understand what is happening... Help?

Thanks!

$timeoutSeconds = 90

ForEach($server in $servers) {
    #$ErrorActionPreference = "inquire"
    #$WarningPreference = "inquire"

    $ErrorActionPreference = "silentlycontinue"
    $WarningPreference = "silentlycontinue"

    write-host $SERVER

    $code = {
        param($SERVER,$LOGto,$outputPath)

        $ping = (Test-Connection -ComputerName $SERVER -Count 2 -Quiet )
        if($ping -eq $true)
        {
            $pingVerbose = (Test-Connection -ComputerName $SERVER -Count 1)
            $IP = $pingVerbose.IPV4Address.IPAddressToString

            $osname2 = (Get-WMIObject -computerName $SERVER win32_operatingsystem).name
            if($osname2 -match "|") 
            {
                $osname,$osname1 = $osname2.Split('|')
            } else {
                $osname = $osname2
            }

            $lastinstalled = (Get-HotFix -computerName $SERVER | where -property InstalledOn -ne $null)
            if($lastinstalled.InstalledOn)
            {
                $lastinstalledOn1 = ($lastinstalled.InstalledOn | Sort-Object -Property InstalledOn )[-1]
                $lastinstalledOn = $lastinstalledOn1
            }

            $lastQFE = (get-wmiobject -class win32_quickfixengineering -computerName $SERVER | where -property InstalledOn -ne $null)
            if($lastQFE.InstalledOn -ne $null)
            {
                $lastQFEon = ($lastQFE.InstalledOn | Sort-Object -Property InstalledOn)[-1]
                $lastQFEon = $lastQFEon
            }

            if(($lastinstalledOn) -or ($lastQFEon))
            {
                if(($lastinstalledOn) -and ($lastinstalledOn -gt $lastQFEon)) 
                {
                    $installedOn = $lastinstalledOn.tostring("MM/dd/yyyy")
                    $HotFixNumber = ($lastinstalled.HotFixID | Sort-Object -Property HotFixID)[-1]
                } else {
                    $installedOn = $lastQFEon.tostring("MM/dd/yyyy")
                    $HotFixNumber = ($lastQFE.HotFixID | Sort-Object -Property HotFixID)[-1]
                }
            } else {
                $installedOn = ''
                $HotFixNumber = ''
            }
        }

    #add entries to the log file
    ac $outputPath\$LOGto "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "
    Write-Host "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "

    }

    $runCode = Start-Job -ScriptBlock $code -ArgumentList $server,$LOGto,$outputPath

    if(Wait-Job $runCode -Timeout $timeoutSeconds) 
    {
        Receive-Job $runCode
    } else {
        Remove-Job -Force $runCode
        ac $($outputPath + "\error.txt")  "$Server"
    }
}

When running in the scriptblock I receive the wrong date and KB.

SERVERNAME
SERVERNAME,10.1.XX.XX,03/13/2015,KB3022777,True,Microsoft Windows Server 2012 R2 Standard 

vs.

SERVERNAME
SERVERNAME,10.1.XX.XX,05/15/2017,KB4012213,True,Microsoft Windows Server 2012 R2 Standard
Luke Fowler
  • 83
  • 2
  • 8
  • With `$lastinstalledOn -gt $lastQFEon` you are comparing STRINGS. Better compare **real dates** or have the date strings in a format that compares correctly like `yyyyMMdd` – Theo Nov 02 '19 at 15:17
  • @Theo tested with your suggestion and results still don't match. Thanks for the suggestion. You are correct about the compare. – Luke Fowler Nov 02 '19 at 15:37
  • That also sortof applies for the sorting you do on the `$HotFixNumber`. While you are getting the date by sorting on `InstalledOn`, you are retrieving the hotfixNumber by sorting on `HotFixID` (which is a string). You should use the same sorting there to get the number for the same hotfix, otherwise you'll probably end up with the wrong number on the correct date. P.S. it is safer to change `if ($lastinstalledOn -gt $null)` to `if ($lastinstalledOn)` – Theo Nov 02 '19 at 15:44
  • @Theo Thanks for the suggestions. I've updated the question to incorporate your fixes. However, the outputs are still different. :-( – Luke Fowler Nov 02 '19 at 15:55

1 Answers1

0

For posterity more than anything else...

The error I was making was using sort-object against a string instead of a numerical value.

The code below will work correctly once you replace the domain name and file path information.

Thanks, -Luke

#change this to a directory of your choice
$outputPath = "C:\Users\username\Desktop"
cd $outputPath

#create a default file name
$LOGto = "AllWinHotFixDateDC_$((Get-Date).ToString('yyyyMMdd')).csv"

#create the headers
sc .\$LOGto "Server,IPAddress,InstalledOn,HotFixNumber,Ping,OS_Name"

#get the server names from AD
Get-ADComputer -Filter {(Enabled -eq "True") -and (OperatingSystem -like "*Windows*") } -SearchBase "OU=Servers,DC=mydomain,DC=net" -server 'mydomain.net' -SearchScope Subtree | Select Name -ExpandProperty name |  Sort-Object | Out-File .\servers.txt
$servers = get-content .\servers.txt

$timeoutSeconds = 90

ForEach($server in $servers) {
    $ErrorActionPreference = "inquire"
    $WarningPreference = "inquire"

    #$ErrorActionPreference = "silentlycontinue"
    #$WarningPreference = "silentlycontinue"

    write-host $SERVER

    $code = {
        param($SERVER,$LOGto,$outputPath)

        $ping = (Test-Connection -ComputerName $SERVER -Count 2 -Quiet )
        if($ping -eq $true)
        {
            $pingVerbose = (Test-Connection -ComputerName $SERVER -Count 1)
            $IP = $pingVerbose.IPV4Address.IPAddressToString

            $osname2 = (Get-WMIObject -computerName $SERVER win32_operatingsystem).name
            if($osname2 -match "|") 
            {
                $osname,$osname1 = $osname2.Split('|')
            } else {
                $osname = $osname2
            }

            $getinstalled = (Get-HotFix -computerName $SERVER)
            if($getinstalled)
            {
                if($getinstalled.HotFixID -ne $null)
                {
                    $validinstalled = ($getinstalled.HotFixID -match "KB*")
                    $KB = (($validinstalled -replace 'KB','') | Sort-Object {[int]($_ -replace '(\d+).*', '$1')})[-1]
                    $lastinstalledOnHotFix = ("KB$KB")
                }
                if ($getinstalled.InstalledOn -ne $null)
                {
                    $lastInstalled = ($getinstalled | Sort-Object -Property InstalledOn)[-1] 
                    $lastInstalledlist = $lastInstalled.InstalledOn  | Sort-Object {[int]($_ -replace '(\d+).*', '$1')}
                    $lastInstalledon = $lastInstalledlist.tostring("MM/dd/yyyy")
                } else {
                    $lastinstalledOn = "0"
                }
            }

            Write-Host $lastinstalledOn
            Write-Host $lastinstalledOnHotFix

            $getQFE = (get-wmiobject -class win32_quickfixengineering -computerName $SERVER )
            if($getQFE)
            {
                if($getQFE.HotFixID -ne $null)
                {
                    $validQFE = ($getQFE.HotFixID -match 'KB')
                    $KB = (($validQFE -replace 'KB','') | Sort-Object {[int]($_ -replace '(\d+).*', '$1')})[-1]
                    $lastQFEonHotFix = ("KB$KB")
                }
                if($getQFE.InstalledOn -ne $null)
                {
                    $lastQFE = ($getQFE | Sort-Object -Property InstalledOn)[-1] 
                    $lastQFElist = $lastQFE.InstalledOn  | Sort-Object {[int]($_ -replace '(\d+).*', '$1')}
                    $lastQFEon = $lastQFElist.tostring("MM/dd/yyyy")
                } else {
                    $lastQFEon = "0"
                }

            }

            Write-Host $lastQFEon
            Write-Host $lastQFEonHotFix

            if(($lastinstalledOn -ne $null) -or ($lastQFEon -ne $null))
            {
                if(($lastInstalledlist -ne $null) -and ($lastInstalledlist -gt $lastQFElist)) 
                {
                    $installedOn = $lastinstalledOn
                    $HotFixNumber = $lastinstalledOnHotFix
                } elseif($lastQFEon -ne $null)
                {
                    $installedOn = $lastQFEon
                    $HotFixNumber = $lastQFEonHotFix
                }
            } else {
                $installedOn = '0'
                $HotFixNumber = $lastQFEonHotFix
            }
        }

    #add entries to the log file
    ac $outputPath\$LOGto "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "
    Write-Host "$Server,$ip,$installedOn,$HotFixNumber,$ping,$osname "

    }

    $runCode = Start-Job -ScriptBlock $code -ArgumentList $server,$LOGto,$outputPath

    if(Wait-Job $runCode -Timeout $timeoutSeconds) 
    {
        Receive-Job $runCode
    } else {
        Remove-Job -Force $runCode
        ac $($outputPath + "\error.txt")  "$Server"
    }
}


Luke Fowler
  • 83
  • 2
  • 8