LostInTheSauce
LostInTheSauce

Reputation: 247

Try Catch not working in Powershell Script

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

}

Upvotes: 21

Views: 71143

Answers (4)

ash
ash

Reputation: 532

  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

Upvotes: 25

Windos
Windos

Reputation: 1946

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
}

Upvotes: 55

eeldivad
eeldivad

Reputation: 53

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] }
}

Upvotes: 2

Ranadip Dutta
Ranadip Dutta

Reputation: 9272

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.

Upvotes: 1

Related Questions