Search code examples
powershellparallel-processingoffice365sccminvoke-command

Invoke-command not returning any value when get-itemproperty return null


I'm attempting to use the builtin parallel processing capabilities of Invoke-Command so I can quickly scan hundreds of machines for Office 365 installations (finding discrepancies in SCCM reporting). However, when Get-ItemProperty can't find the registry key, I'm not sure how to capture the fact that the machine does not have O365.

For example;

<some list of machines>.txt contains
computer1
computer2
computer3

$Computers = Get-Content .\<some list of machines>.txt
Invoke-Command -ComputerName $Computer -ScriptBlock {(Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\O365ProPlusRetail*)} -ErrorAction SilentlyContinue -ErrorVariable Problem | select pscomputername, DisplayName, DisplayVersion

... works really fast and list every machine with O365 and the version. That's great. But missing is every machine that DOES NOT have O365 installed. I.E. if "computer2" in the list above does not have O365, the output shows;

PSComputerName DisplayName                          DisplayVersion
-------------- -----------                          --------------
computer1      Microsoft Office 365 ProPlus - en-us 16.0.9226.2114
computer3      Microsoft Office 365 ProPlus - en-us 16.0.9226.2114

Any ideas on how I could retain parallel processing and get output similar to the following?

PSComputerName DisplayName                          DisplayVersion
-------------- -----------                          --------------
computer1      Microsoft Office 365 ProPlus - en-us 16.0.9226.2114
computer2
computer3      Microsoft Office 365 ProPlus - en-us 16.0.9226.2114

Solution

  • Modify your script block to return a dummy object that signals when the information is not available:

    Invoke-Command -ComputerName $Computer -ScriptBlock {
        $result = Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\O365ProPlusRetail* 
        if (-not $result) { [pscustomobject] @{} } else { $result }
      } -ErrorAction SilentlyContinue -ErrorVariable Problem | 
        Select-Object pscomputername, DisplayName, DisplayVersion
    

    [pscustomobject] @{} creates a custom object without properties, to which the remoting infrastructure automatically adds the .PSComputerName property (among others) on local deserialization; Select-Object will then implicitly add empty .DisplayName and .DisplayVersion properties.