Search code examples
powershelljobs

Get-Printer -AsJob how to find ComputerName on error


We're trying to retrieve all installed printers in bulk. For this we use the -AsJob switch on the Get-Printer CmdLet. This works fine when all ComputerNames exist, but when there's one that doesn't exist an error is correctly thrown.

Example

$ComputerName = @('Computer1', 'NonExisting', 'Computer2')

$GetPrinterJobs = Foreach ($C in $ComputerName) {
    Get-Printer -ComputerName $C -AsJob
}

$GetPrinterJobs | Wait-Job -EA Ignore | Receive-Job

This code will throw one error for the NonExisting ComputerName. How is it possible to see that the error is actually coming from ComputerName NonExisting ?

Get-Printer : The spooler service is not reachable. Ensure the spooler service is running.

With the help below from @JosefZ this is solved as following:

$GetPrinterJobs = Foreach ($C in $ComputerName) {
    $C
    Get-Printer -ComputerName $C -AsJob
}

$null = Get-Job | Wait-Job -EA Ignore

$GetPrinterJobResults = for ( $i = 0; $i -lt $GetPrinterJobs.Count; $i += 2 ) {

    $ReceiveParams = @{
        ErrorVariable = 'JobError'
        ErrorAction   = 'SilentlyContinue'
    }
    $ReceivedJobResult = $GetPrinterJobs[$i + 1] | Receive-Job @ReceiveParams

    [PSCustomObject]@{
        ComputerName = $GetPrinterJobs[$i]
        State        = $GetPrinterJobs[$i + 1].State
        Data         = $ReceivedJobResult
        Error        = if ($JobError) {
            $JobError
            $JobError.ForEach( { $Error.Remove($_) })
        }
    }
}

$GetPrinterJobResults

Solution

  • Here is my old-school workaround:

    $ComputerName = @('Computer1', 'NonExisting', 'Computer2')
    
    $GetPrinterJobs = Foreach ($C in $ComputerName) {
        $C
        Get-Printer -ComputerName $C -AsJob
    }
    
    $GetPrinterJobResults = $GetPrinterJobs | 
        Where-Object { $_.GetType().Name -ne 'String'} | 
            Wait-Job -EA Ignore | Receive-Job
    
    for ( $i = 0; $i -lt $GetPrinterJobs.Count; $i+=2 ) {
        @{
            $GetPrinterJobs[$i] = $GetPrinterJobs[$i + 1].State
        }
    }
    

    Should return something like

    Name          Value                                               
    ----          -----                                               
    Computer1     Completed                                           
    NonExisting   Failed                                              
    Computer2     Completed