PowerShell e l’errore “the property ‘Count’ cannot be found on this object. Verify that the property exists”

Nello sviluppo degli scripts PowerShell, come indicato dalle best practices, è opportuno inserire la seguente direttiva:

Set-StrictMode -Version Latest

Infatti tramite il cmdlet Set-StrictMode, come riportato nel post Enforce Better Script Practices by Using Set-StrictMode si esegue l’enforce delle best practices:

“By using the Set-StrictMode cmdlet, we can enforce some common “best practice” coding techniques that you can use with your scripts.”

“By default, Set-StrictMode is turned off to prevent error messages while you are writing the script.”

Come riportato nella documentazione del cmdlet Set-StrictMode alcuni valori possibili per il parametro –Version in particolare il valore Lastest consente di essere aderenti alle best prctices più restrittive:

1.0:
  • Prohibits references to uninitialized variables, except for uninitialized variables in strings.
2.0:
  • Prohibits references to uninitialized variables. This includes uninitialized variables in strings.
  • Prohibits references to non-existent properties of an object.
  • Prohibits function calls that use the syntax for calling methods.
  • Prohibits a variable without a name (${}).
Latest:
  • Selects the latest version available. The latest version is the most strict. Use this value to make sure that scripts use the strictest available version, even when new versions are added to Windows PowerShell.

Sebbene Latest obbliga la stesura di codice qualitativamente migliore e quindi meno suscettibile ad errori va precisato che non tutti gli errori potrebbero venire rilevati in sede di compilazione e uno di questi è la mancata gestione dei valori nulli.

Scendendo nel partico riporto quanto mi è successo durante la stesura dello script Get-WSUSReportComputersInError.ps1 di cui ho parlato nel post WSUS creazione report per computer con aggiornamenti in errore, in tale script avevo infatti utilizzato la direttiva Set-StrictMode -Version Latest, ma in una porzione di codice che riporto di seguito non avevo gestito il caso del possibile ritorno di un valore nullo:

# Initializations
[reflection.assembly]::LoadWithPartialName(“Microsoft.UpdateServices.Administration”) | out-null
$wsus = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer()
$computerScope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
$updateScope = New-Object Microsoft.UpdateServices.Administration.UpdateScope
$summariesComputerFailed = $wsus.GetSummariesPerComputerTarget($updateScope,$computerScope) | Where-Object FailedCount -NE 0 | Sort-Object FailedCount, UnknownCount, NotInstalledCount –Descending


# Creating the report header
If ($summariesComputerFailed -EQ 0){
$outputText = “No computers were found on the WSUS server (” + $wsus.ServerName + “) with updates in error!”
Write-Host (“`n” + $outputText) -ForegroundColor Green
$reportHtmlHeader = “<font color =’green’><b>” + $outputText + “</b></font>”
}
Else {
$outputText = [string]($summariesComputerFailed).Count + ” computers were found on the WSUS server (” + $wsus.ServerName + “) with failed updates!”
Write-Host (“`n” + $outputText) -ForegroundColor Red
$reportHtmlHeader = “<font color =’red’><b>” + $outputText + “</b></font>”
}


Infatti se la variabile $summariesComputerFailed risulta nulla a runtime viene riportato l’errore “the property ‘Count’ cannot be found on this object. Verify that the property exists.”, come mi è stato segnalato da utente dopo aver reso disponibili lo script anche sulla TechNet Gallery, si veda riguardo la seguente discussione https://gallery.technet.microsoft.com/Get-WSUSReportComputersInEr-daab6605/view/Discussions#content.

Come detto precedentemente la soluzione sta nella gestione anche del caso in cui la variabile abbia un valore nullo modificando come segue il codice, cosa che ho provveduto a fare nella versione 1.4 dello script:

# Creating the report header
If ($summariesComputerFailed -EQ 0 -or $summariesComputerFailed -EQ $null){
$outputText = “No computers were found on the WSUS server (” + $wsus.ServerName + “) with updates in error!”
Write-Host (“`n” + $outputText) -ForegroundColor Green
$reportHtmlHeader = “<font color =’green’><b>” + $outputText + “</b></font>”
}
Else {
$outputText = [string]($summariesComputerFailed).Count + ” computers were found on the WSUS server (” + $wsus.ServerName + “) with failed updates!”
Write-Host (“`n” + $outputText) -ForegroundColor Red
$reportHtmlHeader = “<font color =’red’><b>” + $outputText + “</b></font>”
}