jshizzle
jshizzle

Reputation: 487

PowerShell: Invoke-Command with Try-Catch

I'm using the following code to give me output on the status of a batch of computers:

$Win2k8r2Computers = "Server1", "Server2", "Server3", "Server4"

$results = Invoke-Command -ComputerName $Win2k8r2Computers { #}
    $props = @{}
    Try {
        <#If ($PSVersionTable.PSVersion.Major -eq "2") {
            $props.Add('Message',"Server (Win2008r2) is currently running an incompatible version of PowerShell (v2.1)")
            }#>
        If (Get-Service | Where-Object { $_.Name -eq "W3SVC" } -ErrorAction Stop) {
            $props.Add('Message', "IIS is installed (Win2008r2)")
        }
        Else {
            $props.Add('Message', "IIS is NOT installed (Win2008r2)")
        }
    }
    catch {
        $props.Add('Message', 'Error: {0}' -f $_)
    }
    New-Object -Type PSObject -Prop $Props
}

It's working as expected other than the catch not appearing to actually catch and return errors to the $results variable. What am I missing?

Upvotes: 0

Views: 1994

Answers (1)

zett42
zett42

Reputation: 27806

In your current code, you are passing parameter -ErrorAction only to Where-Object. So you would only catch errors of the Where-Object cmdlet. Get-Service woud still run with the default ErrorAction value of Continue.

To turn errors of both Get-Service and Where-Object into terminating errors that can be catched, either pass -ErrorAction 'Stop' to both of them...

If (Get-Service -ErrorAction Stop | Where-Object { $_.Name -eq "W3SVC" } -ErrorAction Stop)

... or (more efficiently) set the $ErrorActionPreference variable at the beginning of the script and remove the -ErrorAction parameter:

$Win2k8r2Computers = "Server1", "Server2", "Server3", "Server4"

$results = Invoke-Command -ComputerName $Win2k8r2Computers { #}
    $props = @{}
    Try {
        $ErrorActionPreference = 'Stop'

        <#If ($PSVersionTable.PSVersion.Major -eq "2") {
            $props.Add('Message',"Server (Win2008r2) is currently running an incompatible version of PowerShell (v2.1)")
            }#>
        If (Get-Service | Where-Object { $_.Name -eq "W3SVC" }) {
            $props.Add('Message', "IIS is installed (Win2008r2)")
        }
        Else {
            $props.Add('Message', "IIS is NOT installed (Win2008r2)")
        }
    }
    catch {
        $props.Add('Message', 'Error: {0}' -f $_)
    }
    New-Object -Type PSObject -Prop $Props
}

Caveat:

$ErrorActionPreference is ignored by cmdlets in PowerShell script modules, unless they take special care of handling it. See this answer for some insight.

In this case it works though, because both cmdlets are implemented in C# modules.

Upvotes: 1

Related Questions