Try / Catch / Finally

When you use Try / Catch / Finally , the command that will be executed is placed in the Try block . If an error occurs during the execution of the command, then it will be written to the $ Error variable , and the script will go to the Catch block .

The TestTryCatchFinally.ps1 script uses the Try command in an attempt to create an object. The creation object is in the variable $ ob1 . The New-Object cmdlet creates an object. After creating an object and placing it in the $ a variable, you can see the members of the object using the Get-Member cmdlet . The following code illustrates this:

Try
 {
  "Attempting to create new object $ob1"
   $a = new-object $ob1
   "Members of the $ob1"
   "New object $ob1 created"
   $a | Get-Member
 }

Use block Catch to catch the error that occurred in the block the Try . You can specify the type of errors to capture, as well as the action that would occur if an error occurred. In the TestTryCatchFinally.ps1 script , I track errors like System.Exception . The System.Exeption .Net Framework class is the base class on which all other exceptions depend. This means that System.Exeptionis a universal general class, in essence you can get all the predefined exceptions, both general and system. When catching an error, you can specify which code you would like to execute. In this example, I output a simple line that indicates that the script has caught a system exception. The catch block is shown below:

Catch
 {
  [system.exception]
  "caught a system exception"
 }

The Finally block of the Try / Catch / Finally sequence is always executed, regardless of whether an error occurred or not. This means that some things to complete that you want to do, for example, to explicitly free a COM object, should be placed in the Finally block . In the TestTryCatchFinally.ps1 script , the Finally block illustrates the status bar that the script has completed. This is shown below:

Finally
 {
  "end of script"
 }

Entire script TestTryCatchFinally.ps1 :

TestTryCatchFinally.ps1
$ob1 = "kenobie"
"Begin test"
Try
 {
  "Attempting to create new object $ob1"
   $a = new-object $ob1
   "Members of the $ob1"
   "New object $ob1 created"
   $a | Get-Member
 }
Catch [system.exception]
 {
  "caught a system exception"
 }
Finally
 {
  "end of script"
 }

During the execution of the TestTryCatchFinally.ps1 script , when the variable $ ob1 is set to “kenobie”, an error occurs because there is not a single object named “kenobie” that could be created using the New-Object cmdlet . The following picture shows the script output.



As you can see from the previous picture, the “Begin Test” line is displayed because it is outside the scope of the Try / Catch / Finally loop . Inside the Try block, the string “Attempting to create new object kenobie” is displayed because it is executed before the New-Object command . This demonstrates that the try blockalways trying to execute code inside it. Members of the kenobie object are not output, just as the string "new object kenobie created" is not displayed. This indicates that after an error occurs, the script continues to the next block. In the Catch block , an error of type System.Exeption is captured and the string “caught a system exception” is displayed. Next, the script goes to the Finally block and displays the string “end of script”.

If in the script the variable $ ob1 is set to “system.object” (which is the correct value), the Try block will succeed completely. This can be seen in the following figure, the members of the objects are displayed, and a line indicating that the object is successfully created is also displayed. BlockCatch does not work, and the string “end of script” from the Finally block is output.



You can use multiple Catch blocks in a Try / Catch / Finally block . Keep in mind that when an exception occurs, Windows Powershell leaves the Try block and looks for the Catch block . The first Catch block will be used , which will satisfy the exception conditions. Therefore, you need to use the most specific exceptions first, moving on to more general ones.
This is visible in TestTryMultipleCatchFinally.ps1 .

TestTryMultipleCatchFinally.ps1
$ob1 = "foo"
"Begin test"
$ErrorActionPreference = "stop"
Try
 {
  Get-Content foo
  "Attempting to create new object $ob1"
   $a = new-object $ob1
   "Members of the $ob1"
   "New object $ob1 created"
   $a | Get-Member
 }
Catch [System.Management.Automation.PSArgumentException]
 {
  "invalid object"
 }
Catch [system.exception]
 {
  "caught a system exception"
 }
Finally
 {
  "end of script"
 }

The following figure shows the output of the TestTryMultipleCatchFinally.ps1 script . Two changes were made: The $ ErrorActionPreference and Get-Content foo commands were commented out . Thus, the generated error will occur when trying to create a nonexistent object. To find the specific error, I examined the $ error variable after running the TestTryMultipleCatchFinally.ps1 script . The error is indicated in the Exception field .

PS C:\> $error | fl * -F
PSMessageDetails      : 
Exception             : System.Management.Automation.PSArgumentException: Cannot find type
                         [foo]: verify that the assembly containing this type is loaded.
                           at System.Management.Automation.MshCommandRuntime.ThrowTerminat
                        ingError(ErrorRecord errorRecord)
TargetObject          : 
CategoryInfo          : InvalidType: (:) [New-Object], PSArgumentException
FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
ErrorDetails          : 
InvocationInfo        : System.Management.Automation.InvocationInfo
ScriptStackTrace      : at , C:\Users\dyak\SkyDrive\Scripts\habrahabr\TestTry
                        MultipleCatchFinally.ps1: line 10
PipelineIterationInfo : {}




If the script has several errors, and the value of the $ ErroActionPreference variable is set to “stop”, the first error will lead to the script crashing. If you remove comments from the $ ErrorActionPreference and Get-Content commands , the first error will be caught by the System.Exception Catch block and therefore the argument exception will be skipped. This can be seen in the following figure:



In general, I tried to translate an article published in a block by Ed Wilson. I hope it will be useful to someone.

Also popular now: