Powershell error variable

Contribute to devops-collective-inc/big-book-of-powershell-error-handling development by creating an account on GitHub.

Controlling Error Reporting Behavior and Intercepting Errors

This section briefly demonstrates how to use each of PowerShell’s statements, variables and parameters that are related to the reporting or handling of errors.

The $Error Variable

$Error is an automatic global variable in PowerShell which always contains an ArrayList of zero or more ErrorRecord objects. As new errors occur, they are added to the beginning of this list, so you can always get information about the most recent error by looking at $Error[0]. Both Terminating and Non-Terminating errors will be contained in this list.

Aside from accessing the objects in the list with array syntax, there are two other common tasks that are performed with the $Error variable: you can check how many errors are currently in the list by checking the $Error.Count property, and you can remove all errors from the list with the $Error.Clear() method. For example:

image004.png

Figure 2.1: Using $Error to access error information, check the count, and clear the list.

If you’re planning to make use of the $Error variable in your scripts, keep in mind that it may already contain information about errors that happened in the current PowerShell session before your script was even started. Also, some people consider it a bad practice to clear the $Error variable inside a script; since it’s a variable global to the PowerShell session, the person that called your script might want to review the contents of $Error after it completes.

ErrorVariable

The ErrorVariable common parameter provides you with an alternative to using the built-in $Error collection. Unlike $Error, your ErrorVariable will only contain errors that occurred from the command you’re calling, instead of potentially having errors from elsewhere in the current PowerShell session. This also avoids having to clear the $Error list (and the breach of etiquette that entails.)

When using ErrorVariable, if you want to append to the error variable instead of overwriting it, place a + sign in front of the variable’s name. Note that you do not use a dollar sign when you pass a variable name to the ErrorVariable parameter, but you do use the dollar sign later when you check its value.

The variable assigned to the ErrorVariable parameter will never be null; if no errors occurred, it will contain an ArrayList object with a Count of 0, as seen in figure 2.2:

image005.png

Figure 2.2: Demonstrating the use of the ErrorVariable parameter.

$MaximumErrorCount

By default, the $Error variable can only contain a maximum of 256 errors before it starts to lose the oldest ones on the list. You can adjust this behavior by modifying the $MaximumErrorCount variable.

ErrorAction and $ErrorActionPreference

There are several ways you can control PowerShell’s handling / reporting behavior. The ones you will probably use most often are the ErrorAction common parameter and the $ErrorActionPreference variable.

The ErrorAction parameter can be passed to any Cmdlet or Advanced Function, and can have one of the following values: Continue (the default), SilentlyContinue, Stop, Inquire, Ignore (only in PowerShell 3.0 or later), and Suspend (only for workflows; will not be discussed further here.) It affects how the Cmdlet behaves when it produces a non-terminating error.

  • The default value of Continue causes the error to be written to the Error stream and added to the $Error variable, and then the Cmdlet continues processing.
  • A value of SilentlyContinue only adds the error to the $Error variable; it does not write the error to the Error stream (so it will not be displayed at the console).
  • A value of Ignore both suppresses the error message and does not add it to the $Error variable. This option was added with PowerShell 3.0.
  • A value of Stop causes non-terminating errors to be treated as terminating errors instead, immediately halting the Cmdlet’s execution. This also enables you to intercept those errors in a Try/Catch or Trap statement, as described later in this section.
  • A value of Inquire causes PowerShell to ask the user whether the script should continue or not when an error occurs.

The $ErrorActionPreference variable can be used just like the ErrorAction parameter, with a couple of exceptions: you cannot set $ErrorActionPreference to either Ignore or Suspend. Also, $ErrorActionPreference affects your current scope in addition to any child commands you call; this subtle difference has the effect of allowing you to control the behavior of errors that are produced by .NET methods, or other causes such as PowerShell encountering a «command not found» error.

Figure 2.3 demonstrates the effects of the three most commonly used $ErrorActionPreference settings.

image006.png

Figure 2.3: Behavior of $ErrorActionPreference

Try/Catch/Finally

The Try/Catch/Finally statements, added in PowerShell 2.0, are the preferred way of handling terminating errors. They cannot be used to handle non-terminating errors, unless you force those errors to become terminating errors with ErrorAction or $ErrorActionPreference set to Stop.

To use Try/Catch/Finally, you start with the «Try» keyword followed by a single PowerShell script block. Following the Try block can be any number of Catch blocks, and either zero or one Finally block. There must be a minimum of either one Catch block or one Finally block; a Try block cannot be used by itself.

The code inside the Try block is executed until it is either complete, or a terminating error occurs. If a terminating error does occur, execution of the code in the Try block stops. PowerShell writes the terminating error to the $Error list, and looks for a matching Catch block (either in the current scope, or in any parent scopes.) If no Catch block exists to handle the error, PowerShell writes the error to the Error stream, the same thing it would have done if the error had occurred outside of a Try block.

Catch blocks can be written to only catch specific types of Exceptions, or to catch all terminating errors. If you do define multiple catch blocks for different exception types, be sure to place the more specific blocks at the top of the list; PowerShell searches catch blocks from top to bottom, and stops as soon as it finds one that is a match.

If a Finally block is included, its code is executed after both the Try and Catch blocks are complete, regardless of whether an error occurred or not. This is primarily intended to perform cleanup of resources (freeing up memory, calling objects’ Close() or Dispose() methods, etc.)

Figure 2.4 demonstrates the use of a Try/Catch/Finally block:

image007.png

Figure 2.4: Example of using try/catch/finally.

Notice that «Statement after the error» is never displayed, because a terminating error occurred on the previous line. Because the error was based on an IOException, that Catch block was executed, instead of the general «catch-all» block below it. Afterward, the Finally executes and changes the value of $testVariable.

Also notice that while the Catch block specified a type of [System.IO.IOException], the actual exception type was, in this case, [System.IO.DirectoryNotFoundException]. This works because DirectoryNotFoundException is inherited from IOException, the same way all exceptions share the same base type of System.Exception. You can see this in figure 2.5:

image008.png

Figure 2.5: Showing that IOException is the Base type for DirectoryNotFoundException

Trap

Trap statements were the method of handling terminating errors in PowerShell 1.0. As with Try/Catch/Finally, the Trap statement has no effect on non-terminating errors.

Trap is a bit awkward to use, as it applies to the entire scope where it is defined (and child scopes as well), rather than having the error handling logic kept close to the code that might produce the error the way it is when you use Try/Catch/Finally. For those of you familiar with Visual Basic, Trap is a lot like «On Error Goto». For that reason, Trap statements don’t see a lot of use in modern PowerShell scripts, and I didn’t include them in the test scripts or analysis in Section 3 of this ebook.

For the sake of completeness, here’s an example of how to use Trap:

image009.png

Figure 2.6: Use of the Trap statement

As you can see, Trap blocks are defined much the same way as Catch blocks, optionally specifying an Exception type. Trap blocks may optionally end with either a Break or Continue statement. If you don’t use either of those, the error is written to the Error stream, and the current script block continues with the next line after the error. If you use Break, as seen in figure 2.5, the error is written to the Error stream, and the rest of the current script block is not executed. If you use Continue, the error is not written to the error stream, and the script block continues execution with the next statement.

The $LASTEXITCODE Variable

When you call an executable program instead of a PowerShell Cmdlet, Script or Function, the $LASTEXITCODE variable automatically contains the process’s exit code. Most processes use the convention of setting an exit code of zero when the code finishes successfully, and non-zero if an error occurred, but this is not guaranteed. It’s up to the developer of the executable to determine what its exit codes mean.

Note that the $LASTEXITCODE variable is only set when you call an executable directly, or via PowerShell’s call operator (&) or the Invoke-Expression cmdlet. If you use another method such as Start-Process or WMI to launch the executable, they have their own ways of communicating the exit code to you, and will not affect the current value of $LASTEXITCODE.

image010.png

Figure 2.7: Using $LASTEXITCODE.

The $? Variable

The $? variable is a Boolean value that is automatically set after each PowerShell statement or pipeline finishes execution. It should be set to True if the previous command was successful, and False if there was an error.
When the previous command was a PowerShell statement, $? will be set to False if any errors occurred (even if ErrorAction was set to SilentlyContinue or Ignore).
If the previous command was a call to a native exe, $? will be set to False if the $LASTEXITCODE variable does not equal zero. If the $LASTEXITCODE variable equals zero, then in theory $? should be set to True. However, if the native command writes something to the standard error stream then $? could be set to False even if $LASTEXITCODE equals zero. For example, the PowerShell ISE will create and append error objects to $Error for standard error stream output and consequently $? will be False regardless of the value of $LASTEXITCODE. Redirecting the standard error stream into a file will result in a similar behavior even when the PowerShell host is the regular console. So it is probably best to test the behavior in your specific environment if you want to rely on $? being set correctly to True.

Just be aware that the value of this variable is reset after every statement. You must check its value immediately after the command you’re interested in, or it will be overwritten (probably to True). Figure 2.8 demonstrates this behavior. The first time $? is checked, it is set to False, because the Get-Item encountered an error. The second time $? was checked, it was set to True, because the previous command was successful; in this case, the previous command was «$?» from the first time the variable’s value was displayed.

image011.png

Figure 2.8: Demonstrating behavior of the $? variable.

The $? variable doesn’t give you any details about what error occurred; it’s simply a flag that something went wrong. In the case of calling executable programs, you need to be sure that they return an exit code of 0 to indicate success and non-zero to indicate an error before you can rely on the contents of $?.

Summary

That covers all of the techniques you can use to either control error reporting or intercept and handle errors in a PowerShell script. To summarize:

  • To intercept and react to non-terminating errors, you check the contents of either the automatic $Error collection, or the variable you specified as the ErrorVariable. This is done after the command completes; you cannot react to a non-terminating error before the Cmdlet or Function finishes its work.
  • To intercept and react to terminating errors, you use either Try/Catch/Finally (preferred), or Trap (old and not used much now.) Both of these constructs allow you to specify different script blocks to react to different types of Exceptions.
  • Using the ErrorAction parameter, you can change how PowerShell cmdlets and functions report non-terminating errors. Setting this to Stop causes them to become terminating errors instead, which can be intercepted with Try/Catch/Finally or Trap.
  • $ErrorActionPreference works like ErrorAction, except it can also affect PowerShell’s behavior when a terminating error occurs, even if those errors came from a .NET method instead of a cmdlet.
  • $LASTEXITCODE contains the exit code of external executables. An exit code of zero usually indicates success, but that’s up to the author of the program.
  • $? can tell you whether the previous command was successful, though you have to be careful about using it with external commands. If they don’t follow the convention of using an exit code of zero as an indicator of success or if they write to the standard error stream then the resulting value in $? may not be what you expect. You also need to make sure you check the contents of $? immediately after the command you are interested in.

This section briefly demonstrates how to use each of PowerShell’s statements, variables and parameters that are related to the reporting or handling of errors.

$Error is an automatic global variable in PowerShell which always contains an ArrayList of zero or more ErrorRecord objects. As new errors occur, they are added to the beginning of this list, so you can always get information about the most recent error by looking at $Error[0]. Both Terminating and Non-Terminating errors will be contained in this list.

Aside from accessing the objects in the list with array syntax, there are two other common tasks that are performed with the $Error variable: you can check how many errors are currently in the list by checking the $Error.Count property, and you can remove all errors from the list with the $Error.Clear() method. For example:

Figure 2.1: Using $Error to access error information, check the count, and clear the list.

If you’re planning to make use of the $Error variable in your scripts, keep in mind that it may already contain information about errors that happened in the current PowerShell session before your script was even started. Also, some people consider it a bad practice to clear the $Error variable inside a script; since it’s a variable global to the PowerShell session, the person that called your script might want to review the contents of $Error after it completes.

The ErrorVariable common parameter provides you with an alternative to using the built-in $Error collection. Unlike $Error, your ErrorVariable will only contain errors that occurred from the command you’re calling, instead of potentially having errors from elsewhere in the current PowerShell session. This also avoids having to clear the $Error list (and the breach of etiquette that entails.)

When using ErrorVariable, if you want to append to the error variable instead of overwriting it, place a + sign in front of the variable’s name. Note that you do not use a dollar sign when you pass a variable name to the ErrorVariable parameter, but you do use the dollar sign later when you check its value.

The variable assigned to the ErrorVariable parameter will never be null; if no errors occurred, it will contain an ArrayList object with a Count of 0, as seen in figure 2.2:

Figure 2.2: Demonstrating the use of the ErrorVariable parameter.

By default, the $Error variable can only contain a maximum of 256 errors before it starts to lose the oldest ones on the list. You can adjust this behavior by modifying the $MaximumErrorCount variable.

ErrorAction and $ErrorActionPreference

There are several ways you can control PowerShell’s handling / reporting behavior. The ones you will probably use most often are the ErrorAction common parameter and the $ErrorActionPreference variable.

The ErrorAction parameter can be passed to any Cmdlet or Advanced Function, and can have one of the following values: Continue (the default), SilentlyContinue, Stop, Inquire, Ignore (only in PowerShell 3.0 or later), and Suspend (only for workflows; will not be discussed further here.) It affects how the Cmdlet behaves when it produces a non-terminating error.

  • The default value of Continue causes the error to be written to the Error stream and added to the $Error variable, and then the Cmdlet continues processing.

  • A value of SilentlyContinue only adds the error to the $Error variable; it does not write the error to the Error stream (so it will not be displayed at the console).

  • A value of Ignore both suppresses the error message and does not add it to the $Error variable. This option was added with PowerShell 3.0.

  • A value of Stop causes non-terminating errors to be treated as terminating errors instead, immediately halting the Cmdlet’s execution. This also enables you to intercept those errors in a Try/Catch or Trap statement, as described later in this section.

  • A value of Inquire causes PowerShell to ask the user whether the script should continue or not when an error occurs.

The $ErrorActionPreference variable can be used just like the ErrorAction parameter, with a couple of exceptions: you cannot set $ErrorActionPreference to either Ignore or Suspend. Also, $ErrorActionPreference affects your current scope in addition to any child commands you call; this subtle difference has the effect of allowing you to control the behavior of errors that are produced by .NET methods, or other causes such as PowerShell encountering a «command not found» error.

Figure 2.3 demonstrates the effects of the three most commonly used $ErrorActionPreference settings.

Figure 2.3: Behavior of $ErrorActionPreference

The Try/Catch/Finally statements, added in PowerShell 2.0, are the preferred way of handling terminating errors. They cannot be used to handle non-terminating errors, unless you force those errors to become terminating errors with ErrorAction or $ErrorActionPreference set to Stop.

To use Try/Catch/Finally, you start with the «Try» keyword followed by a single PowerShell script block. Following the Try block can be any number of Catch blocks, and either zero or one Finally block. There must be a minimum of either one Catch block or one Finally block; a Try block cannot be used by itself.

The code inside the Try block is executed until it is either complete, or a terminating error occurs. If a terminating error does occur, execution of the code in the Try block stops. PowerShell writes the terminating error to the $Error list, and looks for a matching Catch block (either in the current scope, or in any parent scopes.) If no Catch block exists to handle the error, PowerShell writes the error to the Error stream, the same thing it would have done if the error had occurred outside of a Try block.

Catch blocks can be written to only catch specific types of Exceptions, or to catch all terminating errors. If you do define multiple catch blocks for different exception types, be sure to place the more specific blocks at the top of the list; PowerShell searches catch blocks from top to bottom, and stops as soon as it finds one that is a match.

If a Finally block is included, its code is executed after both the Try and Catch blocks are complete, regardless of whether an error occurred or not. This is primarily intended to perform cleanup of resources (freeing up memory, calling objects’ Close() or Dispose() methods, etc.)

Figure 2.4 demonstrates the use of a Try/Catch/Finally block:

Figure 2.4: Example of using try/catch/finally.

Notice that «Statement after the error» is never displayed, because a terminating error occurred on the previous line. Because the error was based on an IOException, that Catch block was executed, instead of the general «catch-all» block below it. Afterward, the Finally executes and changes the value of $testVariable.

Also notice that while the Catch block specified a type of [System.IO.IOException], the actual exception type was, in this case, [System.IO.DirectoryNotFoundException]. This works because DirectoryNotFoundException is inherited from IOException, the same way all exceptions share the same base type of System.Exception. You can see this in figure 2.5:

Figure 2.5: Showing that IOException is the Base type for DirectoryNotFoundException

Trap statements were the method of handling terminating errors in PowerShell 1.0. As with Try/Catch/Finally, the Trap statement has no effect on non-terminating errors.

Trap is a bit awkward to use, as it applies to the entire scope where it is defined (and child scopes as well), rather than having the error handling logic kept close to the code that might produce the error the way it is when you use Try/Catch/Finally. For those of you familiar with Visual Basic, Trap is a lot like «On Error Goto». For that reason, Trap statements don’t see a lot of use in modern PowerShell scripts, and I didn’t include them in the test scripts or analysis in Section 3 of this ebook.

For the sake of completeness, here’s an example of how to use Trap:

Figure 2.6: Use of the Trap statement

As you can see, Trap blocks are defined much the same way as Catch blocks, optionally specifying an Exception type. Trap blocks may optionally end with either a Break or Continue statement. If you don’t use either of those, the error is written to the Error stream, and the current script block continues with the next line after the error. If you use Break, as seen in figure 2.5, the error is written to the Error stream, and the rest of the current script block is not executed. If you use Continue, the error is not written to the error stream, and the script block continues execution with the next statement.

The $LASTEXITCODE Variable

When you call an executable program instead of a PowerShell Cmdlet, Script or Function, the $LASTEXITCODE variable automatically contains the process’s exit code. Most processes use the convention of setting an exit code of zero when the code finishes successfully, and non-zero if an error occurred, but this is not guaranteed. It’s up to the developer of the executable to determine what its exit codes mean.

Note that the $LASTEXITCODE variable is only set when you call an executable directly, or via PowerShell’s call operator (&) or the Invoke-Expression cmdlet. If you use another method such as Start-Process or WMI to launch the executable, they have their own ways of communicating the exit code to you, and will not affect the current value of $LASTEXITCODE.

Figure 2.7: Using $LASTEXITCODE.

The $? variable is a Boolean value that is automatically set after each PowerShell statement or pipeline finishes execution. It should be set to True if the previous command was successful, and False if there was an error.
When the previous command was a PowerShell statement, $? will be set to False if any errors occurred (even if ErrorAction was set to SilentlyContinue or Ignore).
If the previous command was a call to a native exe, $? will be set to False if the $LASTEXITCODE variable does not equal zero. If the $LASTEXITCODE variable equals zero, then in theory $? should be set to True. However, if the native command writes something to the standard error stream then $? could be set to False even if $LASTEXITCODE equals zero. For example, the PowerShell ISE will create and append error objects to $Error for standard error stream output and consequently $? will be False regardless of the value of $LASTEXITCODE. Redirecting the standard error stream into a file will result in a similar behavior even when the PowerShell host is the regular console. So it is probably best to test the behavior in your specific environment if you want to rely on $? being set correctly to True.

Just be aware that the value of this variable is reset after every statement. You must check its value immediately after the command you’re interested in, or it will be overwritten (probably to True). Figure 2.8 demonstrates this behavior. The first time $? is checked, it is set to False, because the Get-Item encountered an error. The second time $? was checked, it was set to True, because the previous command was successful; in this case, the previous command was «$?» from the first time the variable’s value was displayed.

Figure 2.8: Demonstrating behavior of the $? variable.

The $? variable doesn’t give you any details about what error occurred; it’s simply a flag that something went wrong. In the case of calling executable programs, you need to be sure that they return an exit code of 0 to indicate success and non-zero to indicate an error before you can rely on the contents of $?.

That covers all of the techniques you can use to either control error reporting or intercept and handle errors in a PowerShell script. To summarize:

  • To intercept and react to non-terminating errors, you check the contents of either the automatic $Error collection, or the variable you specified as the ErrorVariable. This is done after the command completes; you cannot react to a non-terminating error before the Cmdlet or Function finishes its work.

  • To intercept and react to terminating errors, you use either Try/Catch/Finally (preferred), or Trap (old and not used much now.) Both of these constructs allow you to specify different script blocks to react to different types of Exceptions.

  • Using the ErrorAction parameter, you can change how PowerShell cmdlets and functions report non-terminating errors. Setting this to Stop causes them to become terminating errors instead, which can be intercepted with Try/Catch/Finally or Trap.

  • $ErrorActionPreference works like ErrorAction, except it can also affect PowerShell’s behavior when a terminating error occurs, even if those errors came from a .NET method instead of a cmdlet.

  • $LASTEXITCODE contains the exit code of external executables. An exit code of zero usually indicates success, but that’s up to the author of the program.

  • $? can tell you whether the previous command was successful, though you have to be careful about using it with external commands. If they don’t follow the convention of using an exit code of zero as an indicator of success or if they write to the standard error stream then the resulting value in $? may not be what you expect. You also need to make sure you check the contents of $? immediately after the command you are interested in.

Skip to content

Powershell Error handling with $ERROR Variable

In all programming, the code will have errors, and troubleshooting those problems will be difficult. Like another programming language, PowerShell has error handling mechanisms for handling the error in our programming.

In PowerShell, errors can be categories in 2 ways one is terminating and non-terminating. As the name implies, a terminating error stops the code execution when the error is thrown. A non-terminating error implies that the code will continue the next line of code execution when an error is shown.

What is the $Error Automatic variable?

It is an Array that holds the terminating and nonterminating errors generated in the shell or The $Error automatic variable contains an array of error objects in the current session.

How does the $Error variable work?

Starting a new PowerShell session the $Error will be empty. Normally, if you run a Windows PowerShell command and an error occurs, the error record will be appended to the “automatic variable” named $ErrorThen we use the $Error[0] to display and access the rest of the information it holds.

Example #1: Starting a new PowerShell session

For this example, we have tried with a new Powershell window session so the $Error variable has empty as shown below

$error[0]

Example #2: Executing the below script which had the error

When an error occurs in our code, it is saved to the Automatic variable named $Error. The $Error variable contains an array of recent errors, and you can reference the most recent error in the array at index 0.

In the below example, the path is not exit and instead of throwing an error we had included -ErrorAction SilentlyContinue, and next line we have written the current error using the $Error variable.

Get-content -Path “C:dotnet-helpersBLOGTestFile.txt” -ErrorAction SilentlyContinue
Write-Warning $Error[0]

Getting Members of $Error Variable

We can use Get-Member to expose your PS variable objects. using the below-listed members we can get deeper into the $Error[0] object to extract

Example #3: Getting the detailed Error using $Error variable

In the below example, we can get deeper into the $Error[0] object to extract the line that failed during execution.

$Error[0].InvocationInfo

#Display the failed code line
Write-Host “Error occured at line : ” $Error[0].InvocationInfo.line

Other Popular Articles

  • Getting Redirected (301/302) URI’s in PowerShell using Invoke-WebRequest Method
  • How to get Sitecore Admin users for the domain using Sitecore PowerShell Extensions
  • .appendTo() method in Jquery
  • How to Create Log File using Start-Transcript cmdlet in PowerShell
  • Exporting and Importing bulk website bindings in IIS
  • animation() Effect in Jquery
  • How to call REST APIs using Powershell
  • How to use appcmd.exe to renew a new certificate for Bulk HTTPS URLs (Bindings)
  • Getting Sitecore User Profile Data Using Sitecore PowerShell Extensions

This site uses Akismet to reduce spam. Learn how your comment data is processed.

About JQuery

Form Data

JQuery Effects

CSS Methods

Manipulation

Page load link

If you are having prior software development experience, for exception handling we generally use PowerShell Try-Catch-Finally block. PowerShell also support try-catch-finally block to handle or respond to terminating errors in PowerShell script.

In PowerShell 2.0, common parameters related to error handling available are: -ErrorAction and -ErrorVariable

In this blog post, I will explain you about using –ErrorAction and –ErrorVariable parameter in PowerShell with examples.

The PowerShell ErrorAction parameter allows you to specify how to respond or handle terminating errors or actions to take if command fails.

ErrorAction parameter has below options available to handle execution of command if error raised

  • Continue
  • Ignore
  • Inquire
  • SilentlyContinue
  • Stop
  • Suspend

Let’s understand each of ErrorAction PowerShell options with examples

-ErrorAction Continue

ErrorAction PowerShell parameter, it basically override the $ErrorActionPreference in Windows PowerShell.

$ErrorActionPreference variable responds to which action to take in case of error raised.

using PowerShell ErrorAction parameter, it default uses continue preference. It means that in the event of error raised, its output will be written to host and script will be able to continue.

Lets consider an example to stop process RabbitMQ and handle any error produced using ErrorAction PowerShell parameter

PS C:> Stop-Process -Name RabbitMQ -ErrorAction Continue; Write-Host "Execute second command"; 

In the above example, Stop-Process cmdlet takes RabbitMQ process name and try to stop it. As it cannot find a process with given name, it throws exception.

Error raised is output to host and using –ErrorAction continue option, it continue with execution for second command.

It converts terminating errors to non-terminating errors to continue with execution and write output to host as given below

PowerShell -ErrorAction Parameter - Continue
PowerShell -ErrorAction Parameter – Continue

Do you know: How to use cat command in windows!

PowerShell -ErrorAction Ignore

PowerShell ErrorAction Ignore option does not produce any error message and write any error output on host and continue with execution.

Using -ErrorAction Ignore option no errors will be updated in PowerShell $Error variable (automatic variable).

Lets consider same example to stop RabbitMQ process. We will use -ErrorAction Ignore option to ignore any error message and continue with execution of second command.

PS C:> Stop-Process -Name RabbitMQ -ErrorAction Ignore; Write-Host "Execute second command"; 

Output of above command is as below

PowerShell -ErrorAction Parameter - Ignore
PowerShell -ErrorAction Parameter – Ignore

PowerShell Tip: How to add newline to string or variable?

-ErrorAction Inquire

PowerShell ErrorAction Inquire option produce an error and prompt user to confirm actions to take

a. Yes b. Yes to All c. Halt Command d. Suspend

Based on users action, it decide to continue with execution or halt or suspend it.

Let’s consider above example to stop RabbitMQ process using Stop-Process. We will use -ErrorAction Inquire option to let user to confirm action in the case of error produced

PS C:>> Stop-Process -Name RabbitMQ -ErrorAction Inquire; Write-Host "Execute second command";   

Output of the above command with user selection as Yes

PowerShell -ErrorAction Parameter - Inquire
PowerShell -ErrorAction Parameter – Inquire

If the user select Halt Command, it will write error message on Host and halt further execution. If the user select Suspend option, it will suspend the current execution.

Cool Tip: Replace text in string using PowerShell!

PowerShell -ErrorAction SilentlyContinue

ErrroAction SilentlyContinue in PowerShell silently continue with the execution of code if the part of code does not work or have non-terminating errors.

PowerShell ErrorAction SilentlyContinue option silence non-terminating errors and continue execution. Error will updated in PowerShell Error variable (automatic variable).

Let’s consider example to stop process name as RabbitMQ using Stop-Process. We will use -ErrorAction SilentlyContinue option to silence non-terminating errors and execution of second command.

PS C:>>> Stop-Process -Name RabbitMQ -ErrorAction SilentlyContinue; Write-Host "Execute second command";    

Output of the above command is as below

PowerShell -ErrorAction Parameter - SilentlyContinue
PowerShell -ErrorAction Parameter – SilentlyContinue

Cool Tip: Get-ChildItem cmdlet – Search for files in PowerShell!

-ErrorAction Stop

PowerShell ErrorAction Stop option display error message on host and stop further execution of code. It terminates the code.

Lets consider similar example given above to find process name as RabbitMQ. We will use -ErrorAction Stop option to check execution.

PS C:>>> Stop-Process -Name RabbitMQ -ErrorAction Stop; Write-Host "Execute second command"; 

The output of the above command is as below

PowerShell -ErrorAction Parameter - Stop
PowerShell -ErrorAction Parameter – Stop

-ErrorAction Suspend

PowerShell -ErrorAction Suspend option available in PowerShell workflows. If error raised in command, workflows will get suspended.

Cool Tip: Best way to use PowerShell Get-ChildItem cmdlet!

PowerShell ErrorVariable Parameter

When you run PowerShell command, in the event of error raised, error will added into PowerShell $Error automatic variable.

Using PowerShell ErrorVariable parameter, you can specify your own variable name to store error message.

PowerShell ErrorVariable will overwrite error message value to variable name. If you want to append error in variable name, use + in front of variable name. It will append error message.

Let’s consider an example to illustrate -ErrroVariable in PowerShell. We will use same example given above to stop process name as RabbitMQ. As command not able to find process, it will raise error.

Using -ErrorVariable PowerShell, we will store error message in processError variable name as given below

PS C:>>> Stop-Process -Name RabbitMQ -ErrorVariable processError;    

In the above command, it will add error message on PowerShell Error variable as well as on to processvariable variable.

If we print processError variable name, it will write error output on host as given below

PowerShell -ErrorVariable - variable
PowerShell -ErrorVariable – variable

Cool Tip: Get-FileHash cmdlet – Get MD5 checksum in PowerShell!

You can make the use of -ErrorAction and -ErrorVariable together to silent non-terminating errors and add error message in variable to take further action

Using the same example given above with -ErrorAction SilentlyContinue option and -ErrorVariable to store error message in processError variable.

PS C:>>> Stop-Process -Name RabbitMQ -ErrorAction SilentlyContinue -ErrorVariable processError;                        PS C:>>> $processError   

In the above code, SilentlyContinue option in PowerShell silent non-terminating errors and -ErrorVariable parameter add error message to processError variable as given below

powershell erroraction silentlycontinue
PowerShell -ErrorAction and -ErrorVariable

Cool Tip: Read more about PowerShell $PSScriptRoot Automatic Variable!

Conclusion

I hope you may have like above detailed article about PowerShell ErrorAction parameter and -ErrorVariable PowerShell parameter.

Using different options available with -ErrorAction, we can handle error message in code.

You can find more topics about PowerShell Active Directory commands and PowerShell basics on ShellGeek home page.

В Powershell существует несколько уровней ошибок и несколько способов их обработать. Проблемы одного уровня (Non-Terminating Errors) можно решить с помощью привычных для Powershell команд. Другой уровень ошибок (Terminating Errors) решается с помощью исключений (Exceptions) стандартного, для большинства языков, блока в виде Try, Catch и Finally. 

Как Powershell обрабатывает ошибки

До рассмотрения основных методов посмотрим на теоретическую часть.

Автоматические переменные $Error

В Powershell существует множество переменных, которые создаются автоматически. Одна из таких переменных — $Error хранит в себе все ошибки за текущий сеанс PS. Например так я выведу количество ошибок и их сообщение за весь сеанс:

Get-TestTest
$Error
$Error.Count

Переменная $Error в Powershell

При отсутствии каких либо ошибок мы бы получили пустой ответ, а счетчик будет равняться 0:

Счетчик ошибок с переменной $Error в Powershell

Переменная $Error являет массивом и мы можем по нему пройтись или обратиться по индексу что бы найти нужную ошибку:

$Error[0]

foreach ($item in $Error){$item}

Вывод ошибки по индексу в Powershell c $Error

Свойства объекта $Error

Так же как и все что создается в Powershell переменная $Error так же имеет свойства (дополнительную информацию) и методы. Названия свойств и методов можно увидеть через команду Get-Member:

$Error | Get-Member

Свойства переменной $Error в Powershell

Например, с помощью свойства InvocationInfo, мы можем вывести более структурный отчет об ошибки:

$Error[0].InvocationInfo

Детальная информация об ошибке с $Error в Powershell

Методы объекта $Error

Например мы можем очистить логи ошибок используя clear:

$Error.clear()

Очистка логов об ошибке в Powershell с $Error

Критические ошибки (Terminating Errors)

Критические (завершающие) ошибки останавливают работу скрипта. Например это может быть ошибка в названии командлета или параметра. В следующем примере команда должна была бы вернуть процессы «svchost» дважды, но из-за использования несуществующего параметра ‘—Error’ не выполнится вообще:

'svchost','svchost' | % {Get-Process -Name $PSItem} --Error 

Критические ошибки в Powershell Terminating Errors

Не критические ошибки (Non-Terminating Errors)

Не критические (не завершающие) ошибки не остановят работу скрипта полностью, но могут вывести сообщение об этом. Это могут быть ошибки не в самих командлетах Powershell, а в значениях, которые вы используете. На предыдущем примере мы можем допустить опечатку в названии процессов, но команда все равно продолжит работу:

'svchost111','svchost' | % {Get-Process -Name $PSItem}

Не критические ошибки в Powershell Non-Terminating Errors

Как видно у нас появилась информация о проблеме с первым процессом ‘svchost111’, так как его не существует. Обычный процесс ‘svchost’ он у нас вывелся корректно.

Параметр ErrorVariable

Если вы не хотите использовать автоматическую переменную $Error, то сможете определять свою переменную индивидуально для каждой команды. Эта переменная определяется в параметре ErrorVariable:

'svchost111','svchost' | % {Get-Process -Name $PSItem } -ErrorVariable my_err_var
$my_err_var

Использование ErrorVariable в Powershell

Переменная будет иметь те же свойства, что и автоматическая:

$my_err_var.InvocationInfo

Свойства  ErrorVariable в Powershell

Обработка некритических ошибок

У нас есть два способа определения последующих действий при ‘Non-Terminating Errors’. Это правило можно задать локально и глобально (в рамках сессии). Мы сможем полностью остановить работу скрипта или вообще отменить вывод ошибок.

Приоритет ошибок с $ErrorActionPreference

Еще одна встроенная переменная в Powershell $ErrorActionPreference глобально определяет что должно случится, если у нас появится обычная ошибка. По умолчанию это значение равно ‘Continue’, что значит «вывести информацию об ошибке и продолжить работу»:

$ErrorActionPreference

Определение $ErrorActionPreference в Powershell

Если мы поменяем значение этой переменной на ‘Stop’, то поведение скриптов и команд будет аналогично критичным ошибкам. Вы можете убедиться в этом на прошлом скрипте с неверным именем процесса:

$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem}

Определение глобальной переменной $ErrorActionPreference в Powershell

Т.е. скрипт был остановлен в самом начале. Значение переменной будет храниться до момента завершения сессии Powershell. При перезагрузке компьютера, например, вернется значение по умолчанию.

Ниже значение, которые мы можем установить в переменной $ErrorActionPreference:

  • Continue — вывод ошибки и продолжение работы;
  • Inquire — приостановит работу скрипта и спросит о дальнейших действиях;
  • SilentlyContinue — скрипт продолжит свою работу без вывода ошибок;
  • Stop — остановка скрипта при первой ошибке.

Самый частый параметр, который мне приходится использовать — SilentlyContinue:

$ErrorActionPreference = 'SilentlyContinue'
'svchost111','svchost' | % {Get-Process -Name $PSItem}

Игнорирование ошибок в Powershell с ErrorActionPreference и SilentlyContinue

Использование параметра ErrorAction

Переменная $ErrorActionPreference указывает глобальный приоритет, но мы можем определить такую логику в рамках команды с параметром ErrorAction. Этот параметр имеет больший приоритет чем $ErrorActionPreference. В следующем примере, глобальная переменная определяет полную остановку скрипта, а в параметр ErrorAction говорит «не выводить ошибок и продолжить работу»:

$ErrorActionPreference = 'Stop'
'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'SilentlyContinue'}

Использование параметра ErrorAction в ошибках с Powershell

Кроме ‘SilentlyContinue’ мы можем указывать те же параметры, что и в переменной $ErrorActionPreference. 

Значение Stop, в обоих случаях, делает ошибку критической.

Обработка критических ошибок и исключений с Try, Catch и Finally

Когда мы ожидаем получить какую-то ошибку и добавить логику нужно использовать Try и Catch. Например, если в вариантах выше мы определяли нужно ли нам отображать ошибку или останавливать скрипт, то теперь сможем изменить выполнение скрипта или команды вообще. Блок Try и Catch работает только с критическими ошибками и в случаях если $ErrorActionPreference или ErrorAction имеют значение Stop.

Например, если с помощью Powershell мы пытаемся подключиться к множеству компьютеров один из них может быть выключен — это приведет к ошибке. Так как эту ситуацию мы можем предвидеть, то мы можем обработать ее. Процесс обработки ошибок называется исключением (Exception).

Синтаксис и логика работы команды следующая:

try {
    # Пытаемся подключиться к компьютеру
}
catch [Имя исключения 1],[Имя исключения 2]{
    # Раз компьютер не доступен, сделать то-то
}
finally {
    # Блок, который выполняется в любом случае последним
}

Блок try мониторит ошибки и если она произойдет, то она добавится в переменную $Error и скрипт перейдет к блоку Catch. Так как ошибки могут быть разные (нет доступа, нет сети, блокирует правило фаервола и т.д.) то мы можем прописывать один блок Try и несколько Catch:

try {
    # Пытаемся подключится
}
catch ['Нет сети']['Блокирует фаервол']{
    # Записываем в файл
}
catch ['Нет прав на подключение']{
    # Подключаемся под другим пользователем
}

Сам блок finally — не обязательный и используется редко. Он выполняется самым последним, после try и catch и не имеет каких-то условий.

Catch для всех типов исключений

Как и было показано выше мы можем использовать блок Catch для конкретного типа ошибок, например при проблемах с доступом. Если в этом месте ничего не указывать — в этом блоке будут обрабатываться все варианты ошибок:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch {
   Write-Host "Какая-то неисправность" -ForegroundColor RED
}

Игнорирование всех ошибок с try и catch в Powershell

Такой подход не рекомендуется использовать часто, так как вы можете пропустить что-то важное.

Мы можем вывести в блоке catch текст ошибки используя $PSItem.Exception:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch {
   Write-Host "Какая-то неисправность" -ForegroundColor RED
   $PSItem.Exception
}

Переменная PSITem в блоке try и catch в Powershell

Переменная $PSItem хранит информацию о текущей ошибке, а глобальная переменная $Error будет хранит информацию обо всех ошибках. Так, например, я выведу одну и ту же информацию:

$Error[0].Exception

Вывод сообщения об ошибке в блоке try и catch в Powershell

Создание отдельных исключений

Что бы обработать отдельную ошибку сначала нужно найти ее имя. Это имя можно увидеть при получении свойств и методов у значения переменной $Error:

$Error[0].Exception | Get-Member

Поиск имени для исключения ошибки в Powershell

Так же сработает и в блоке Catch с $PSItem:

Наименование ошибок для исключений в Powershell

Для вывода только имени можно использовать свойство FullName:

$Error[0].Exception.GetType().FullName

Вывод типа ошибок и их названия в Powershell

Далее, это имя, мы вставляем в блок Catch:

try {
   'svchost111','svchost' | % {Get-Process -Name $PSItem -ErrorAction 'Stop'}
}
catch [Microsoft.PowerShell.Commands.ProcessCommandException]{
   Write-Host "Произошла ошибка" -ForegroundColor RED
   $PSItem.Exception
}

Указываем исключение ошибки в блоке Try Catch Powershell

Так же, как и было описано выше мы можем усложнять эти блоки как угодно указывая множество исключений в одном catch.

Выброс своих исключений

Иногда нужно создать свои собственные исключения. Например мы можем запретить добавлять через какой-то скрипт названия содержащие маленькие буквы или сотрудников без указания возраста и т.д. Способов создать такие ошибки — два и они тоже делятся на критические и обычные.

Выброс с throw

Throw — выбрасывает ошибку, которая останавливает работу скрипта. Этот тип ошибок относится к критическим. Например мы можем указать только текст для дополнительной информации:

$name = 'AD.1'

if ($name -match '.'){
   throw 'Запрещено использовать точки в названиях'
}

Выброс ошибки с throw в Powershell

Если нужно, то мы можем использовать исключения, которые уже были созданы в Powershell:

$name = 'AD.1'

if ($name -like '*.*'){
   throw [System.IO.FileNotFoundException]'Запрещено использовать точки в названиях'
}

Выброс ошибки с throw в Powershell

Использование Write-Error

Команда Write-Error работает так же, как и ключ ErrorAction. Мы можем просто отобразить какую-то ошибку и продолжить выполнение скрипта:

$names = @('CL1', 'AD.1', 'CL3')

foreach ($name in $names){
   if ($name -like '*.*'){
      Write-Error -Message 'Обычная ошибка'
   }
   else{
      $name
   }
}

Использование Write-Error для работы с исключениями в Powershell

При необходимости мы можем использовать параметр ErrorAction. Значения этого параметра были описаны выше. Мы можем указать значение ‘Stop’, что полностью остановит выполнение скрипта:

$names = @('CL1', 'AD.1', 'CL3')

foreach ($name in $names){
   if ($name -like '*.*'){
      Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'
   }
   else{
      $name
   }
}

Использование Write-Error и Stop в Powershell

Отличие команды Write-Error с ключом ErrorAction от обычных команд в том, что мы можем указывать исключения в параметре Exception:

Write-Error -Message 'Обычная ошибка' -ErrorAction 'Stop'

Write-Error -Message 'Исключение' -Exception [System.IO.FileNotFoundException] -ErrorAction 'Stop'

Свойства Write-Errror в Powershell

В Exception мы так же можем указывать сообщение. При этом оно будет отображаться в переменной $Error:

Write-Error -Exception [System.IO.FileNotFoundException]'Моё сообщение'

Свойства Write-Errror в Powershell 

Теги:

#powershell

#ошибки

Продолжаем «работу над ошибками» 🙂 В прошлый раз я рассказал о параметре командлетов -ErrorAction, а сегодня займёмся его соседом -ErrorVariable. Как можно догадаться из названия, он указывает переменную в которую будет помещён объект ошибки (да, в PowerShell даже ошибки являются объектами 😉 ). Но тут возникает одна популярная ошибка. Обычно все (в том числе и я 😉 ) пробуют указать в качестве аргумента этой команде переменную 😉

[PS <24> C:Root] Get-Process -id 1234 -ErrorVariable $MyError
Get-Process : Cannot find a process with the process identifier 1234.
At line:1 char:12
+ Get-Process <<<<  -id 1234 -ErrorVariable $MyError

Казалось бы всё правильно, произошла ошибка, и соответствующий объект был помещен в переменную $MyError? Ан нет, такой переменной даже не существует. В чём же дело? А в том что парсер PowerShell’а, разбирая эту строчку увидел символ $ и понял что следом за ним идет переменная, которую надо преобразовать в её значение перед передачей команде (логично ведь? 😉 ). А так как такой переменной не существует, PowerShell поступил так же как он обычно поступает с неназначенными переменными — передал вместо неё … ничего. То есть параметр -ErrorVariable не получил названия переменной в которую ему следовало поместить ошибку. Думаю уже понятно что для того чтобы этого не произошло, надо указывать просто название переменной, без символа $:

[PS <25> C:Root] Get-Process -id 1234 -ErrorVariable MyError
Get-Process : Cannot find a process with the process identifier 1234.
At line:1 char:12
+ Get-Process <<<<  -id 1234 -ErrorVariable MyError
[PS <26> C:Root] $MyError
Get-Process : Cannot find a process with the process identifier 1234.
At line:1 char:12
+ Get-Process <<<<  -id 1234 -ErrorVariable MyError

Итак объект с ошибкой у нас есть, что же с ним можно делать дальше?

Нет! Ни в коем случае не парсить! Хотя это и можно сделать — это было бы в корне неправильно. У нас в руках полноценный объект, с очень полезными свойстами к которым можно обращаться без всяких заморочек с разбором текста (который кстати может отличатся не только у разных ошибок, но и при использовании разных языков).

И тут возникает вторая тонкость. При попытке посмотреть свойства ошибки перенаправив её на команду Format-List * нас ждёт жестокий облом:

[PS <27> C:Root] $MyError | Format-List *
Get-Process : Cannot find a process with the process identifier 1234.
At line:1 char:12
+ Get-Process <<<<  -id 1234 -ErrorVariable MyError

На выходе получился не ожидаемый список всех свойств, а тот же самый текст. Чтобы этого не случилось, надо добавить к Format-List параметр -Force:

[PS <28> C:Root] $MyError | Format-List * -Force

Exception             : Microsoft.PowerShell.Commands.ProcessCommandException: Cannot find a process with the process identifier 1234.
TargetObject          : 1234
CategoryInfo          : ObjectNotFound: (1234:Int32) [Get-Process], ProcessCommandException
FullyQualifiedErrorId : NoProcessFoundForGivenId,Microsoft.PowerShell.Commands.GetProcessCommand
ErrorDetails          :
InvocationInfo        : System.Management.Automation.InvocationInfo

Еще стоит обратить внимание на то что $MyError является массивом. В случае если при выполнении команды произойдет несколько ошибок — все они будут помещены в переменную, и ни одна не потеряется. И поэтому если мы хотим посмотреть например свойство InvocationInfo то следует указать индекс элемента:

[PS <29> C:Root] $MyError[0].InvocationInfo

MyCommand             : Get-Process
CommandLineParameters : {[Id, System.Int32[]]}
ScriptLineNumber      : 1
OffsetInLine          : 12
ScriptName            :
Line                  : Get-Process -id 1234 -ErrorVariable MyError
PositionMessage       :
                        At line:1 char:12
                        + Get-Process <<<<  -id 1234 -ErrorVariable MyError
InvocationName        : Get-Process
PipelineLength        : 1
PipelinePosition      : 1
ExpectingInput        : False
CommandOrigin         : Runspace

Ну и конечно можно получить только значение конкретного свойства. И без всякого парсинга 😉 Например позицию в строке на которой произошла ошибка:

[PS <30> C:Root] $MyError[0].InvocationInfo.OffsetInLine
12

Это разумеется еще не всё про ошибки, ждите продолжений 😉

PowerShell

As with any programming language, code will have errors and troubleshooting those problems can be difficult. Thankfully, PowerShell has a rich error object and several powerful tools to help debug your code.

With PowerShell 7, these tools become even more useful and error handling even easier. As the language evolves and becomes used in more places than ever, being able to quickly and efficiently troubleshoot a problem will prove invaluable to integrating the language into common workflows.

Table of Contents

  • Understanding Errors in PowerShell
    • Terminating Errors
    • Non-Terminating Errors
  • Error Views
  • The Error Object Behind the Scenes
  • The New Get-Error Cmdlet
    • Exception
    • TargetObject
    • CategoryInfo
    • FullyQualifiedErrorId
    • InvocationInfo
    • ScriptStackTrace
  • Conclusion

Understanding Errors in PowerShell

Broadly speaking, PowerShell errors fall into two categories, terminating and non-terminating. Though these concepts are worth articles in their own right, a terminating error implies that code execution is stopped when the error is thrown. A non-terminating error implies that the code will continue despite an error message being shown.

Terminating Errors

As you can see below, the text “This should never be shown”, is not shown, as the terminating error stops code execution. The function throw will always return a terminating error.

Figure 1 – Terminating Error Output

Non-Terminating Errors

It is more difficult to arbitrarily generate a non-terminating error, but one easy way is to use the Get-ChildItem cmdlet and ask the cmdlet to find a nonexistent directory. As you can tell the command Write-Host "This text will show!", does in fact appear.

Figure 2 – Non-Terminating Error Output

You can turn most non-terminating errors into terminating errors by modifying an individual cmdlet’s ErrorAction to Stop. For example, Get-ChildItem "missing_dir" -ErrorAction 'Stop'

Error Views

You might notice that in the previous output, there are two different views of the error information. Figure 1 shows the NormalView of the $ErrorView preference variable. This view was standard and traditional until PowerShell 7. Starting with PowerShell 7, the default view has changed to what you see in Figure 2 and that is of the ConciseView. It dispenses with much of the decoration around the output, but as you might be able to tell, some information is not made available.

The Error Object Behind the Scenes

Underlying the data behind the error output is the $Error object that is populated by PowerShell when errors are thrown. To view this data, you are able to output and walk through the information. The traditional way to get the last error thrown is by calling $Error[0]. This uses array notation to reference the error.

Figure 4 – $Error Object

If you happen to mistype this command, you will overwrite the first object in the error collection with the new error, so be careful when referencing this object.

As you can see there is the same error as originally shown, but we want to view more of the data. By selecting all of the properties, we are able to see what’s available. As we will talk about in the next section, the Get-Error cmdlet provides a rich view of this data, but it’s important to understand what is going on underneath.

Figure 5 – Error Object Properties

By walking through each property we can see what information exists between the Get-Error cmdlet and the $Error object itself.

Figure 6 – Error Object Exception Properties

The New Get-Error Cmdlet

That brings us to the next PowerShell 7 addition and that is the Get-Error cmdlet. To expand upon the ConciseView and show far more detail, we can run the Get-Error cmdlet and see the expanded details of the last error thrown.

Related article: Error Handling With PowerShell Try Catch Blocks

Figure 3 – Get-Error Output

There is a lot of information shown here, so let’s break down what is useful.

Exception

  • Type – Basic Exception Information
  • ErrorRecordMost of this information is from the $Error object itself. The TargetObject, CategoryInfo, and FullyQualifiedErrorId are all duplicated further in the Get-Error output. What is useful is the Exception data.
    • Type – An exception, but could be referencing the parent exception
    • Message – The human-readable error message
    • HResult – Traditional numerical error code that Windows has used since the early days of the operating system
  • ItemName – The same as the TargetObject shown later in the Get-Error output
  • SessionStateCategory – A series of values that errors fall into, this is an enum underneath
  • TargetSite – A set of information that exposes some of the internal PowerShell engine values and where the error itself is coming from
  • StackTrace – This is the actual method signature of where the error itself came from and can help aid in why an error was shown
  • Message – The human-readable error message
  • Source – This is the source of where the error is coming from
  • HResult – As discussed above, the traditional numerical error code from Windows

TargetObject

The object that the function, cmdlet, or code targets, in this case D:\missing_dir

CategoryInfo

A concatenated view of several different properties, breaking down to the below format:

<Error>: (<TargetObject>:<ObjectType>) [<Originating CmdLet>], <Exception Type>

FullyQualifiedErrorId

The FullyQualifiedErrorId is Message property of the exception object combined with the fully-qualified name of the class where the exception originated.

InvocationInfo

  • MyCommand – The originating cmdlet or function throwing the error
  • ScriptLineNumber – Location within the file or ScriptBlock that the error is thrown
  • OffsetInLine – The location within the line that the error was thrown
  • HistoryId – The location from within the Get-History cmdlet that the error was thrown
  • Line – The command throwing the error
  • PositionMessage – Combined information for the error
  • InvocationName – The cmdlet or function throwing the error
  • CommandOrigin – In what context the error was thrown

ScriptStackTrace

Contained here is information on where in a script the error occurred. In this case, the error occurred on line 1, but this will reflect the line of the error in the given ScriptBlock.

Conclusion

Unlike other programming languages, PowerShell provides a very rich error object to figure out what went wrong and help to debug troublesome code. With PowerShell 7, the ability to decipher errors is even easier with the introduction of the Get-Error cmdlet. Furthermore, the ConciseView of the ErrorAction preference will keep the command line free from clutter and make coding even easier!

Для начала определимся, что такое обработка ошибок вообще. В общем случае ошибка — это поведение программы или скрипта, отличное от запланированного. Совсем избежать ошибок не очень возможно, поэтому надо предвидеть, где они могут возникнуть и писать код так, чтобы при возникновении ошибки можно было перехватить ее, проанализировать и определить дальнейшее поведение скрипта.  Именно это обычно и подразумевается под обработкой ошибок.

В PowerShell ошибки делятся на два типа: прерывающие (Terminating) и непрерывающие (Non-Terminating). Как следует из названия, непрерывающие ошибки позволяют продолжить выполнение команды, тогда как при возникновении прерывающей ошибки дальнейшее продолжение выполнения команды невозможно. К примеру, у нас есть файл со списком служб, которые необходимо перезапустить следующей командой:

Get-Content -Path C:Filesservices.txt | Restart-Service

Предположим, что перезапуск одной из перечисленных служб по какой либо причине невозможен. Тем не менее можно продолжать выполнение задачи, поскольку остальные службы доступны и их можно перезапустить. Это пример непрерывающей ошибки.

А теперь представьте, что у нас нет прав на открытие этого файла, и соответственно прочитать список служб мы не можем. В этой ситуации продолжение работы невозможно, т.е. это прерывающая ошибка.

PowerShell позволяет обрабатывать оба эти типа ошибок. Большинство ошибок в PowerShell непрерывающие, и сегодня речь пойдет о том, как их обрабатывать.

Обработка непрерывающих ошибок

Для получения ошибки возьмем службу с ″оригинальным″ названием Service. Поскольку службы этой на сервере нет, то обращение к ней стабильно будет генерировать ошибку. Запросим данные о нескольких службах командой:

Get-Service service,spooler

Как видно из примера, PowerShell не нашел службу Service, о чем выдал ошибку и затем продолжил выполнение команды. Давайте разберемся, почему команда повела себя именно так и как это поведение изменить.

обработка ошибки по умолчанию

За поведение команды при возникновении ошибки отвечает параметр ErrorAction, который может принимать одно из пяти значений:

• Continue;
• SilentlyContinue;
• Stop;
• Ignore;
• Inquire.

Примечание. Еще у ErrorAction может быть значение Suspend. Но это значение может применяться только к рабочим процессам (workflows), поэтому в рамках данной статьи речь о нем не пойдет.

Значение Continue означает, что при возникновении ошибки информация об этом будет выведена на экран (отправлена в поток вывода Error) и добавлена в автоматическую переменную $Error, после чего выполнение команды будет продолжено. Надо сказать, что Continue — это действие, определенное в сеансе по умолчанию, поэтому его можно не указывать явно.

обработка ошибки, режим Continue

При значении SilentlyContinue информация об ошибке добавляется в переменную $Error, но не выводится на экран. При этом команда продолжает выполняться дальше, также как и в предыдущем случае.

обработка ошибки, режим SilentlyContinue

Значение Stop останавливает дальнейшее выполнение команды при возникновении ошибки. И наоборот, значение Ignore полностью игнорирует возникновение ошибки, при этом не выводится сообщение на экран и не производится запись в $Error. Это значение появилось в PowerShell 3.0.

Обработка ошибок в режимах Stop и Ignore

Inquire — наиболее интересное значение ErrorAction. Если задать это значение, то при возникновении ошибки предлагается на выбор несколько действий: продолжить (Yes), продолжить не смотря на эту и все последующие ошибки (Yes to All), остановить (Halt) или приостановить (Suspend) выполнение команды.

Самый необычный эффект дает Suspend, при выборе которого открывается параллельный сеанс (Nested Namespace). Определить его можно по значку >>. Nested Namespace представляет из себя дочерний процесс, в котором можно полноценно работать — выполнять команды, запускать скрипты и т.п. Этот режим удобно использовать для отладки скриптов, например можно по быстрому исправить причину ошибки и продолжить выполнение. Для выхода из Nested Namespace достаточно набрать exit и выбрать необходимое действие.

Обработка ошибки в режиме Inquire

Примечание. У параметра ErrorAction есть алиас — EA. Кроме того, вместо названия параметра можно указывать числовые значения: 0 (SilentlyContinue), 1 (Stop), 2 (Continue), 3 (Inquire). Так например, вместо:

Get-Service service,spooler -ErrorAction SilentlyContinue

можно написать так:

Get-Service service,spooler -EA 0

Переменные для обработки ошибок

Как я уже говорил, если не указывать параметр ErrorAction, то для команды действует режим обработки ошибок, определенный в сеансе. Этот режим задается переменной $ErrorActionPreference, которая по умолчанию имеет значение Continue. При желании можно переопределить режим для всего сеанса, задав переменной $ErrorActionPreference нужное значение.

Политика обработки ошибок по умолчанию

Все ошибки PowerShell сохраняет в автоматическую переменную $Error. Это глобальная переменная, которая представляет из себя массив строк, содержащий записи обо всех ошибках в текущем сеансе. Каждая новая ошибка добавляется в начало массива, соответственно для просмотра последней ошибки надо обратиться к самому первому элементу массива $Error[0].

$Error имеет свои свойства и методы, которые можно использовать. Например, посмотреть общее количество ошибок в текущем сеансе можно командой $Error.Count, а очистить список — командой $Error.Clear().

переменная $Error

Переменная $Error не безразмерна, по умолчанию она хранит не более 256 ошибок. При превышении этого количества наиболее старые ошибки будут затираться. При необходимости количество записей в переменной $Error можно увеличить, изменив значение другой переменной $MaximumErrorCount.

Кроме $Error для хранения ошибок допускается задавать собственные переменные. Сделать это можно с помощью параметра ErrorVariable, например так:

Get-Service service,spooler -ErrorAction SilentlyContinue -ErrorVariable var

Обратите внимание, что имя переменной в команде задается без знака $, хотя в дальнейшем к ней обращаемся как к обычной переменной $var.

назначение собственной переменной для хранения ошибок

В отличие от глобальной переменной $Error заданные вручную переменные хранят только ошибки той команды, в которой они определены. Кроме того, по умолчанию эти переменные каждый раз перезаписываются и поэтому хранят только последнюю ошибку. Если вы хотите, чтобы новые ошибки добавлялись в переменную, не перезаписывая ее содержимое, то перед именем переменной надо поставить знак +, например +var.

Пока все, а в следующей части пойдет о способах обработки прерывающих ошибок.

Понравилась статья? Поделить с друзьями:
  • Powershell error clear
  • Powershell error action
  • Powerpoint сбой активации продукта как исправить
  • Powerpoint разрывает слова как исправить
  • Powerpoint произошла серьезная ошибка во время последнего запуска