21

I cannot seem to get this try-catch to work. I am sure it is something simple, but my brain is just too fried at this very moment. PLEASE HELP!

param(
[String[]]$RemoteServicesVMs = ('VmThatThrowsError')
)

function getWinServiceStatus
{

#Get-WmiObject "win32_service" 
    try{

        Get-WmiObject "win32_service" | Where-Object {$_.startname -notlike "NT*" -and $_.startname -notlike "local*" } | Format-Table -property PSComputerName, name, state, status, startname

    }  
    catch{

        wite-host "Failed"

    }

}

$PassWordEnc = convertto-securestring $RemotePassWord -asplaintext -force
$MyCred = New-Object -TypeName System.Management.Automation.PSCredential ArgumentList $RemoteUserName,$PassWordEnc

foreach($RemoteServicesVM in $RemoteServicesVMs){

    Invoke-Command -ComputerName $RemoteServicesVM -Port 5985 -Authentication Negotiate -ScriptBlock ${function:getWinServiceStatus} -Credential $MyCred

}
1

4 Answers 4

56

Try/Catch will only 'trigger' on a terminating exception. Most cmdlets in PowerShell, by default, won't throw terminating exceptions. You can set the error action with the -ErrorAction or -ea parameters:

Do-Thing 'Stuff' -ErrorAction Stop

In saying that... I don't think Get-WmiObject will ever generate a terminating error. If it doesn't find something it just won't return anything. In this case you can have an if condition inside your try block, and manually throw:

Try {
    $Obj = Get-WmiObject "win32_service" | Where ...
    if ($null -eq $Obj) {
        throw
    }
}
Catch {
    # Error Handling
}
Sign up to request clarification or add additional context in comments.

Comments

26
  1. Your catch statement has a typo. It should be Write-Host

  2. Try-catching in Powershell is different to most other programming languages. There are 2 types of errors in Powershell, terminating and non-terminating. By default, a non-terminating error will not trigger your catch handling.

So, if you want to force powershell to catch the error no matter what type it is, you can append -ErrorAction Stop to your Invoke-Command line.

Eg:

Invoke-Command -ComputerName $RemoteServicesVM -Port 5985 -Authentication Negotiate -ScriptBlock ${function:getWinServiceStatus} -Credential $MyCred -ErrorAction Stop

Or (as copied from the link below):

It is also possible to treat all errors as terminating using the ErrorActionPreference variable. You can do this either for the script your are working with or for the whole PowerShell session. To set it in a script, make the first line $ErrorActionPreference = Stop. To set it for the session, type $ErrorActionPreference = Stop at the PowerShell console.

See more here: http://www.vexasoft.com/blogs/powershell/7255220-powershell-tutorial-try-catch-finally-and-error-handling-in-powershell

2 Comments

There's actually two kinds of terminating errors. One kind will end the whole script, while the other kind won't, but can still be used in a try/catch.
I had to put quotes around the word stop in my script or the command would not work: $ErrorActionPreference = "Stop"
2

Instead of try/catch you can check to see if the last command ran successfully or not and then handle it:

Get-WmiObject "win32_service"
if(!$?){
  if($error[0].exception.message -match "invalid class"){ write-warning "The class doesn't exist"}
  else{ throw $error[0] }
}

Comments

1

I modified your function param a little bit , but for your answer , I have to say since you are using notlike your get-wmiobject is not returning any error.

If data is not there also , it will show you blank. You can narrow down the issue by putting the output in the variable and displaying the output.

You should use -eq with wildcard to deal with it.

For narrowing down the issue, use this:

$erroractionpreference = stop;
function getWinServiceStatusparam(
[String[]]$RemoteServicesVMs = ('VmThatThrowsError')
)
{

#Get-WmiObject "win32_service" 
    try{

       $a=  Get-WmiObject "win32_service" | Where-Object {$_.startname -notlike "NT*" -and $_.startname -notlike "local*" } | Format-Table -property PSComputerName, name, state, status, startname
       Write-Host $a
    }  
    catch{

        wite-host "Failed"

    }

}

$PassWordEnc = convertto-securestring $RemotePassWord -asplaintext -force
$MyCred = New-Object -TypeName System.Management.Automation.PSCredential ArgumentList $RemoteUserName,$PassWordEnc

foreach($RemoteServicesVM in $RemoteServicesVMs){

    Invoke-Command -ComputerName $RemoteServicesVM -Port 5985 -Authentication Negotiate -ScriptBlock ${function:getWinServiceStatus} -Credential $MyCred

}

Hope it helps.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.