Invoke-Command connection errors

I’m feeding an Invoke-Command a list of servers to run a script and return results. Everything works as I want, except for servers that it cannot connect to (obviously).

What I would like is to have the script also output a list of the computers that were unable to successfully connect with the Invoke-Command, so I know which ones were offline and not part of the results (instead of just seeing the default error messages).

The important part of the code currently looks something like this:

$Results = @()
$Results = invoke-command -computername ‘PC1’,‘PC2’,‘OfflinePC’,‘PC3’,‘PC4’
{get-service}
write-output $Results

You probably need to do one computer at a time, so that when one fails, you know which one it was.

$computers = @('PC1','PC2','OfflinePC','PC3','PC4')
foreach ($computer in $computers) {
  Try {
    Invoke-Command -Script { get-service } -Computer $computer -ErrorAction Stop
  } catch {
    Write-Warning "$computer failed"
  }
}

You don’t get parallelization that way, though. A different approach would be to use jobs.

invoke-command -computername 'PC1','PC2','OfflinePC','PC3','PC4' -AsJob

You’ll get a master job for the entire command, with sub-jobs that track each machine. You’ll be able to run Receive-Job to get the results, and easily see which ones failed.

IMHO, there’s no need to do an invoke command when using get-service.

try this, It will list the failed computer name in the error message.

$Servers = (‘localhost’,‘Server1’,‘Computer2’)

foreach($Server in $Servers){
$Output = Get-Service -ComputerName $Server | select machinename,status,name,displayname
$Output
}

The get-service command was just an example. I’m actually doing something more complicated in the invoke-command, but I didn’t want to confuse the question with that information.

I will try the AsJob code and see how that goes.

Thanks!

“The get-service command was just an example. I’m actually doing something more complicated in the invoke-command”

Please post, I’m interested in learning more about using the invoke-command.

Here’s the full script. I stole the heart of it from another script that did much more than I needed it to do. The thing I needed was just to see which computers were offline and which still had uninstalled updates, so I could tell that my scheduled install of server updates actually got them all installed and that nobody was still rebooting. I coded the ability to get the update data as the only output, but for my usual purposes it just displays that and then a list of offline computers and a list of computers needing updates.

Function Get-PendingWindowsUpdates
{

[CmdletBinding()]
Param(
    [Parameter(Mandatory=$True,Position=1,ParameterSetName='List')]
        [string[]]$ComputerName='localhost',
    [Parameter(Mandatory=$False)]
        [switch]$RawOutput
)

Begin {

    Remove-Job 'MSPatch' -ErrorAction SilentlyContinue

    Invoke-Command -ComputerName $ComputerName -AsJob -JobName MSPatch -ScriptBlock {

        Write-Verbose "Start of script on $Computer"
        #$VerbosePreference=$Using:VerbosePreference
        $Computer = $env:COMPUTERNAME

        $UpdateCollection = @()
        Write-Verbose "Create Microsoft.Update.Session object for $Computer"
        $objSession =  [activator]::CreateInstance([type]::GetTypeFromProgID("Microsoft.Update.Session",$Computer))

        Write-Verbose "Create Microsoft.Update.Session.Searcher object for $Computer"
        $objSearcher = $objSession.CreateUpdateSearcher()

        $objResults = $objSearcher.Search("IsInstalled = 0")
        $PreFoundUpdatesToDownload = $objResults.Updates.count
        Write-Verbose "Found [$PreFoundUpdatesToDownload] Updates in pre search criteria"				

        Foreach($Update in $objResults.Updates)
        {

	        $Status = ""
	        If($Update.IsDownloaded)    {$Status += "D"} else {$status += "-"}
	        If($Update.IsInstalled)     {$Status += "I"} else {$status += "-"}
	        If($Update.IsMandatory)     {$Status += "M"} else {$status += "-"}
	        If($Update.IsHidden)        {$Status += "H"} else {$status += "-"}
	        If($Update.IsUninstallable) {$Status += "U"} else {$status += "-"}
	        If($Update.IsBeta)          {$Status += "B"} else {$status += "-"} 

	        Add-Member -InputObject $Update -MemberType NoteProperty -Name ComputerName -Value $Computer
	        Add-Member -InputObject $Update -MemberType NoteProperty -Name KB -Value $Update.KBArticleIDs
	        Add-Member -InputObject $Update -MemberType NoteProperty -Name Size -Value $Update.MaxDownloadSize
	        Add-Member -InputObject $Update -MemberType NoteProperty -Name Status -Value $Status

	        $Update.PSTypeNames.Clear()
	        $Update.PSTypeNames.Add('PSWindowsUpdate.WUList')
            
            If ($Update.IsDownloaded) {$UpdateCollection += $Update}
        } #End Foreach $Update in $objResults.Updates				

        $FoundUpdatesToDownload = $UpdateCollection.count
        Write-Verbose "Found [$FoundUpdatesToDownload] Updates in post search criteria"
        Return $UpdateCollection				
    } #End Invoke

    Get-Job 'MSPatch' | Wait-Job

    $JobList = Get-Job 'MSPatch' -IncludeChildJob
    $ComputerFailed = @()
    $ComputerHasPatch = @()
    $UpdateAllList = @()

    ForEach ($Job in $Joblist) {
        If ($Job.name -like 'Job*') {
            Write-Verbose $Job.Location
            If ($Job.state -like "Failed") {
                Write-Verbose "Computer is offline"
                $ComputerFailed += $Job.Location
            }
            If ($Job.HasMoreData -eq $True) {
                Write-Verbose "Computer has patches"
                $ComputerHasPatch += $Job.Location
                $UpdateAllList += Receive-Job $Job.Id
            }
        }
    }
    Remove-Job 'MSPatch' -ErrorAction SilentlyContinue

    If ($RawOutput) {
        Write-Output $UpdateAllList
    } else {
        $UpdateAllList | Sort-Object -Property Computername,KB | Format-Table -Property ComputerName,KB,Size,Status,Title -AutoSize 
        Write-Output "Computers with updates"
        $ComputerHasPatch
        Write-Output ""
        Write-Output "Offline Computers"
        $ComputerFailed
    }
}

} #End Function Get-PendingWindowsUpdates