Need help with WSUS reporting

I know this has probably been beat to death but I really don’t have any experience (yet) with powershell, and just getting my feet wet with WSUS.
All i want is to create a script, that when run, outputs in tabular form as a .csv, all the pcs/servers on our network (which isn’t many) that are not up to date with the patches we have on our WSUS server. Put another way, it will reference WSUS and then give a list of all pcs/servers that have not received those patches.

As of now, the script just outputs a csv with a couple of ';;'s. It gives an error message, but I can’t make heads or tails of the message.


#cls
$datetime = Get-Date -Format "yyyy.MM.dd_HH-mm-ss";
$domain = "ourdomain.local";
$file_name = "wsus_audit_result_" + $domain + "_" + $datetime + ".csv";
$xl_filename = "c:\audit\" + $file_name;
 
[void][reflection.assembly]::LoadWithPartialName("Microsoft.UpdateServices.Administration")
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpdateServer('WSUSServerName.OURDOMAIN.Local', $false)
 
$computerscope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
$computerscope.IncludeSubgroups = $true;
$computerscope.IncludeDownstreamComputerTargets = $true;
$computerscope.IncludedInstallationStates = [Microsoft.UpdateServices.Administration.UpdateInstallationStates] "Failed, NotInstalled, Downloaded";
 
$updates = $wsus.GetUpdates() | where {$_.IsApproved -eq $true};
 
$array = @{};
foreach ($update in $updates) {
    $temp = $update.GetUpdateInstallationInfoPerComputerTarget($ComputerScope) | where {$_.UpdateApprovalAction -eq "Install"}
         
    if ($temp -ne $null) {
        foreach ($item in $temp) {
            $array.($wsus.GetComputerTarget([guid]$item.ComputerTargetId).FulldomainName)++;
        }
    }
}
 
$export_array = @();
$export_array += ,@("");$export_array += ,@("");
 
$i = 1;
foreach ($key in $array.Keys) {
    if ($key.split(".")[1] -eq $domain.split(".")[0]) {
        $export_array += ,@($key.Split(".")[0], $key.Split(".")[1], $array.$key);
    }
}
 
echo "Saving report ...";
foreach($item1 in $export_array) 
{ 
    $csv_string = "";
    foreach($item in $item1)
    {
        $csv_string = $csv_string + $item + ";";
    }
    Add-Content $xl_filename $csv_string;
}

The error message is as follows:


Exception calling "GetUpdateServer" with "2" argument(s): "The request failed with HTTP status 404: Not Found."
At C:\Audit\report.ps1:8 char:1
+ $wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::getUpda ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : WebException
 
You cannot call a method on a null-valued expression.
At C:\Audit\report.ps1:15 char:1
+ $updates = $wsus.GetUpdates() | where {$_.IsApproved -eq $true};
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

Thank you so much (in advance)

Anyone?

This would be such a HUGE help…

I would try changing your update server host to reflect the exact syntax/URL that you have configured on your clients. Should be something like “https://WSUSServername.OURDOMAIN.local:8531

The error you are getting indicates the “URL”/404 is not found.

Hmmm. interesting… ok i’ll look into that.

would that also cause the strange output? all i get is a .csv with a couple of ';;'s in on of the cells…

thanks for your input! i’ll let you know how it goes

Yes, I do believe with your second error being “You cannot call a method on a null-valued expression” … that is why your CSV is basically empty.

also, why the syntax matter on the clients?
I have this script located in a local folder on our Wsus server.
in the script, i have both the domain declaration and ‘getUpdateServer’ function with the exact syntax
as on the WSUS server.

Not sure I understand the question? Basically, WSUS works through IIS and it is accessed from the clients via a URL, not a hostname, hence the reason I suggested using the URL. My reference to the “clients” was related to configuring WSUS via GPO and the setting for that under: Admin Templates/Windows Settings/Windows Updates/Specify intranet Microsoft Update location

I was referring to that so you could get an example of what the URL needed to be.

1 Like