Powershell get error code

How to verify whether an external command in PowerShell was executed successfully or not by its errorlevel: PowerShell exit code.

Here is how you can verify whether an external command in PowerShell was executed successfully or not by its errorlevel. Simply by verifying the PowerShell exit code.

The terms exit code, return value or ErrorLevel can be used interchangeably.

Powershell $? operator

The PowerShell operator $? contains True if the last operation succeeded and False otherwise.

# source: # http://blogs.msdn.com/b/powershell/archive/2006/09/15/errorlevel-equivalent.aspx if( $? ) { # True, last operation succeeded } if( !$? ) { # Not True, last operation failed }

Code language: PHP (php)

To illustrate PowerShell’s $? usage, have a look at the following DISM Cleanup-Image command. In my Windows Server disk cleanup using DISM blogpost, I’ve shown you how to clean up your Windows Server WinSxs folder with DISM.

Those commands are easily wrapped into a PowerShell script, and here it is:

$os_version = [System.Environment]::OSVersion.Version # The above returns 6.3.9600.0 for Server 2012 R2 or # 10.0.14393.0 for Server 2016. Server 2012 matches # 6.2.9200.0, and so on. # # See https://msdn.microsoft.com/nl-nl/library/windows/desktop/ms724832(v=vs.85).aspx # for more information about Windows Server versions. $cleanup = $false # Always be careful comparing strings and integers! if( $os_version -ge ( New-Object System.Version "10.0" )) { # $os_version is greater than, or equal to "10.0", so # this is Windows Server 2016. } if( $os_version -ge ( New-Object System.Version "6.3" ) -And $os_version -le ( New-Object System.Version "10.0" )) { # $os_version is greater than 6.3 and smaller than 10.0, # therefore this must be Windows Server 2012 R2 &dism.exe /online /Cleanup-Image /StartComponentCleanup /ResetBase | Write-Output if( $? ) { # dism cleanup-image was successful, set variable to True $cleanup = $true } } if ( $cleanup ) { # Dism.exe was executed Write-Host "[*] System going down for reboot in 3 seconds!" &shutdown /r /f /t 3 } else { # an error occurred Write-Host "[*] Something went wrong with DISM and Cleanup-Image, ` please perform the actions by hand." }

Code language: PHP (php)

How can I stop PowerShell errors from being displayed in a script?

Suppress error messages in PowerShell like a pro :) If you don’t want to display PowerShell errors completely, you can wrap your PowerShell commands in a Try{} / Catch{} block. For example:

Get-Website | % { $sitename = $_.name; try{ $handlers = Get-WebConfiguration /system.webServer/handlers/add -Location $sitename If( $handlers.scriptProcessor -like "x:php73php-cgi.exe*" ) { write-output "$sitename uses PHP 7.3" &appcmd.exe recycle apppool $sitename # Restart-WebAppPool $sitename } } catch {} }

Code language: PHP (php)

This checks the registred handler to see if scriptProcessor contains x:php73php-cgi.exe*. If so, recycle that website’s application pool (assuming the website and apppool names are the same).

By using a Try{} / Catch{} block, you don’t see the PowerShell errors like:

Get-WebConfiguration : Filename: ?z:siteswwwexample.comwwwweb.config Line number: 14 Error: There is a duplicate 'system.web.extensions/scripting/scriptResourceHandler' section defined At line:3 char:13 $handlers = Get-WebConfiguration /system.webServer/handlers/add -Loca … ~~~~~~~~~~~~~ CategoryInfo : NotSpecified: (:) [Get-WebConfiguration], COMException FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.IIs.PowerShell.Provider.GetConfigu rationCommand

Code language: PHP (php)

PowerShell’s $LASTEXITCODE

The PowerShell $LASTEXITCODE should be 0, since $LASTEXITCODE contains the exit code of the last Win32 executable execution.

$LASTEXITCODE the equivalent to cmd.exe %ERRORLEVEL%, and you can use it as follows in your PowerShell scripts:

&dism.exe /Online /Cleanup-Image /StartComponentCleanup /ResetBase if( $LASTEXITCODE -eq 0 ) { Write-Output "Command executed successfully" # do something, like `Restart-Computer -Force` } else { Write-Output "Last command failed" }

Code language: PHP (php)

Display
Error Codes with PowerShell

September 16, 2003

Powershell

Display Error Codes with Microsoft PowerShell

My mission on this page is to show you how to display error codes, furthermore, I will explain how to translate meaningless numbers into meaningful phrases.

Topics for Error Codes in PowerShell

  • Example 1: How to Create a PowerShell Function
  • Example 2: Using a PowerShell Function to Display Error Codes

 ♣

Mission to Display Error Messages When Creating Shares

We need a vehicle to examine error codes.  That vehicle will be creating a file share.  For example, if the share already exists, when you run the script again, it returns error code 22.  Not only can we trap this return value, but also we can ‘Switch’ 22 to a more meaningful message, such as ‘Duplicate Share’

Example 1: How to Create a PowerShell Function

Naturally, any function needs a name, in this case I chose ‘errMsg’.  As this is a simple function, it only has one argument, $intErr. The rest of the function is taken up with a ‘Switch’ statement, or a series of statements corresponding to each error value.

# Microsoft PowerShell Function only
# Author: Guy Thomas
# Version 1.1 March 2008 tested on PowerShell v 1.0

Function errMsg($intErr)
{
Switch($intErr)
{
0 { «Success – Share created» }
2 { «Access denied – Permission?» }
8 { «Unknown failure» }
9 { «Invalid name» }
10 { «Invalid level» }
21 { «Invalid parameter» }
22 { «Duplicate share – Already created» }
23 { «Redirected path» }
24 { «Unknown device or directory» }
25 { «Net name not found» }
DEFAULT { «$intErr has an Unknown value» }
}
}

Note 1:  This code does not do anything by itself, it is merely a stage in producing the script.

Example 2: Using a PowerShell Function to Display an Error Code

Preparation and Pre-requisites

To understand Example 2, I suggest that you familiarise yourself with the logic of my ‘Create a Share‘ example.  Then you can match my thinking to the second portion of the script below.

When you understand my script, copy and paste the code into PowerShell, or better, create a cmdlet with .ps1 extension.  Then call that file from within PowerShell with ./filename.

# Using a PowerShell Function
# Author: Guy Thomas
# Version 2.3 March 2008 tested on PowerShell v 1.0

Function errMsg($intErr)
{
   Switch($intErr)
     {
      0 { «Success – Share created» }
      2 { «Access denied – Permission?» }
      8 { «Unknown failure» }
      9 { «Invalid name» }
    10 { «Invalid level» }
    21 { «Invalid parameter» }
    22 { «Duplicate share – Already created» }
    23 { «Redirected path» }
    24 { «Unknown device or directory» }
    25 { «Net name not found» }
     DEFAULT { «$intErr has an Unknown value» }
     }
}

$FolderPath = «C:Temp»
$ShareName = «Temporary»
$Type = 0
$Description = «Guy and PowerShell»
$class = «Win32_share»
$objWMI = [wmiClass] ‘Win32_share’
$Success=$objWMI.create($FolderPath, $ShareName, $Type)
errMsg($Success.returnValue)

Note 1:  Working backwards! On the last line, errMsg($Success.returnValue) runs a number through the function, which I created in the first part of the script.  The result is a meaningful message controlled by that function’s Switch statement.

Note 2:  Next, let us study the $Success variable.  $Success=$objWMI…. results in an attempt to create the share, however, it exits, therefore the .returnValue is 22.

See more WMI share tasks for PowerShell »

»

Summary: Error Codes in PowerShell

All good Microsoft PowerShell scripts should have error correcting code.  The first step is to trap the .returnValue; closely followed by switching the number for a meaningful phrase.

If you like this page then please share it with your friends


See more PowerShell share examples including WMI

• PowerShell WMI   • Create Win32_Share   • WMI Shares   • Free Permissions Analyzer Tool

• Get-Acl  • PowerShell Share Error Codes   • Win32_ComputerSystem  • PowerShell 3.0 CIM

• Windows PowerShell  • Free WMI Monitor  • Cacls   • Query   • PowerShell Printer Scripts

Please email me if you have a example scripts.  Also please report any factual mistakes, grammatical errors or broken links, I will be happy to correct the fault.

About The Author

Guy Thomas

Welcome to my Getting Started with Windows PowerShell series!

Why Handle Errors?

Error handling may take some extra time to create, however, it can really save you time in the long run. Let’s say you have a script that performs the following tasks:

  • Takes information from a database / file and stores it in $userAccounts

  • Uses a loop to perform processing on each $user in $userAccounts

    • Update a user’s AD information if the user is in the list

    • Disable any accounts that are not in the list

The script runs, and seems to be working great for a few weeks. Then, all of a sudden, the database server goes down, and $userAccounts is empty. The script runs, doesn’t see any users, and what likely happens next is all user accounts are deleted. While this example is a little extreme, it is something that can happen. There are also a lot of in-between cases that can make error handling worth it. It’s a good mindset to have when you’re writing scripts as you can write to incorporate it off the bat.

Errors in PowerShell

Errors in PowerShell are stored in the automatic variable $error. You can see how many errors you’ve encountered in your session by using:

$error.count

This is essentially an array of errors, to access the first value you can use:

$error[0]

Let’s take a look at $error[0] more closely, via:

$error[0] | Get-Member

We can view information on the command that raised the error via:

$error[0].InvocationInfo

It looks like the line property contains the full command we used when the error was encountered.

$error[0].InvocationInfo.Line

The exception that raised the error can be accessed via:

$error[0].Exception

We can also get more information about the exception via:

$error[0].Exception | Get-Member

Here you can see the TypeName: [System.UnauthorizedAccessException], and the various methods and properties of the exception. The exception TypeName is used later when we catch specific errors.

Looks like to get the exception’s message in string format we’d use:

$error[0].Exception.Message

Now that we’ve dug into the automatic variable $error, let’s move on to the different types of errors we can encounter.

Terminating Errors

Terminating errors in PowerShell mean that the script can no longer continue to run with the information it has encountered, or has been given. If you do not have a way to catch the error, it will likely display the nasty red error text you’ve likely seen before. Terminating errors halt anything running in the pipeline. This terminates output, aside from the error message of the terminating error. 

Here’s an example of a terminating error that was caused by calling a command that does not exist:

Get-TerminatingError

Non-Terminating Errors

Non-terminating errors in PowerShell do not stop the pipeline from executing. These errors are handled internally by the Cmdlet, and are not able to be captured via error handling. There are ways, however, to make PowerShell treat non-terminating errors like terminating errors. That way we can use error handling to capture what’s going on.

Here’s an example of a non-terminating error (access denied to a subfolder), when attempting to list all folders and subfolders in «C:Windowsappcompat».

Get-ChildItem -Path 'C:Windowsappcompat' -Recurse

Force Non-Terminating Errors to Terminate

You can force non-terminating errors to become terminating errors in PowerShell. There are a couple ways you can do this. Why would you want to do this, you ask? Since non-terminating errors cannot be handled by us, we need to force them to terminate, and gain the functionality of handling the error ourselves. This is not always needed, but it is good to know that you can do it if you come across a use case for yourself.

$errorActionPreference

You can do it at a global way for the session via the $ErrorActionPreference variable. This is a special variable in PowerShell that allows you to control what happens when a non-terminating error is encountered.

Here are the values for $ErrorActionPreference.

  • Stop

    • Display error, and stop execution.

  • Inquire

    • Display error, and ask to continue.

  • Continue (Default)

    • This is the default setting. Display error, then continue execution.

  • Suspend

    • This one is for workflows. A workflow job is suspended to investigate what happened, then the workflow can be resumed.

  • SilentlyContinue

    • No error is displayed, execution is continued.

Let’s see this in action.

Get-ChildItem -Path 'C:Windowsappcompat' -Recurse;Write-Host 'Test'

As you can see, with a non-terminating error, the next command in the sequence is executed. Therefore we see ‘Test’. Let’s set the $errorActionPreference automatic variable to Stop, and re-run the same command.

$ErrorActionPreference = 'Stop'
Get-ChildItem -Path 'C:Windowsappcompat' -Recurse;Write-Host 'Test'

Use the Command’s -ErrorAction Parameter

Cmdlet’s and functions/scripts/modules that use [cmdletbinding()] enable utilization of the -ErrorAction common parameter. This parameter allows you to specify different actions to take when an error is encountered. 

  • Stop

    • Display error, and stop execution.

  • Inquire

    • Display error, and ask to continue.

  • Continue (Default)

    • This is the default setting. Display error, then continue execution.

  • Suspend

    • This one is for workflows. A workflow job is suspended to investigate what happened, then the workflow can be resumed.

  • SilentlyContinue

    • No error is displayed, execution is continued.

  • Ignore

    • The same as SilentlyContinue, but as SilentlyContinue still adds the message to the $error automatic variable, Ignore does not do this.

Let’s set our $errorActionPreference to Continue, and then look at using the Cmdlet Get-ChildItem‘s -ErrorAction parameter.

We’re setting $errorActionPreference back to Continue as earlier we set it to Stop for our other example. Continue is the default value.

$ErrorActionPreference = 'Continue'
Get-ChildItem -Path 'C:Windowsappcompat' -Recurse -ErrorAction Stop;Write-Host 'Test'

Error Handling

There are a few different ways to to handle errors in PowerShell. The best way of course, is to never let them happen in the first place! To do that, it is good to have some data validation in place via an if statement, or whichever method suites your needs.

If a terminating error occurs, we can use Try/Catch/Finally blocks to perform different actions. If it is non-terminating, we can force it to become a terminating error, and then choose how to continue.

Validation

The simplest method of validation is the if statement. 

If you’d like to run these examples yourself, go ahead and fire up the PowerShell ISE. Save a file in C:PowerShell as part11.ps1. 

An if statement is constructed as follows:

if (condition -eq $true) {

Do-Stuff

} else {

Do-Other-Stuff

}

The condition can be anything that resolves to a true value. That includes running a command that output (other than and error) occurs! Check this out:

if (Get-ChildItem Z: -ErrorAction SilentlyContinue) {

    Write-Host 'I can list the contents of Z:!'

} else {

    Write-Host 'I cannot list the contents of Z:!'

}

This does not return true, as expected, and thus we see the message from the code in the else portion of the if statement. We use the -ErrorAction common parameter with the value SilentlyContinue to suppress the error from being displayed to the end user of the script. No need in this case, as we’re simply using the command for validation.

You can also use variables with the if statement to see if they are blank. 

$myVariable = $null

if ($myVariable) {

    Write-Host "We have information! Let's do stuff."

} else {

    Write-Host "`$myVariable is empty :("

}

The variable is empty, so the code in the else portion of the if statement is executed.

Try/Catch/Finally

The Try, Catch, and Finally blocks in PowerShell allow us to capture terminating errors. 

The Try block contains the code you’d like to execute, and catch any potential errors that happen.

The Catch block contains the code you’d like to execute after a terminating error has occurred. The current error will be accessible via the automatic variable $_.

The Finally block contains the code you’d like to run after the event has occurred. This is good for cleanup tasks. 

It is worth noting that finally block is not required.

Here is an example using Try/Catch/Finally:

Try {
    
    $command = 'Invoke-FakeCommand'

    Write-Host "Attempting to run: [Invoke-Expression -Command $command]"`n

    Invoke-Expression -Command $command

}

Catch {

    Write-Host $_.Exception.Message`n

}

Finally {

    Write-Host "Clean up: `$commmand = `$null"`n

    $commmand = $null

}

The code in the Try block executes and we see the output of Write-Host. We then see the error message that occurs, as our Catch block is writing out $_.Exception.Message. As we learned earlier, that is the string value of the exception that raised the error.

We then see the output from the Write-Host command in our Finally block. We use the finally block to free up the $command variable.

This version of Try/Catch will catch any terminating errors that are raised. To capture specific exceptions, you’ll want to use the exception’s TypeName.

Catch Specific Errors

Let’s take a look at the following:

Try {

    Get-ThisWontWork

}

Catch [System.Management.Automation.CommandNotFoundException] {
    
    Write-Host "Command not found!"`n -ForegroundColor Red 
    Write-Host "Message: [$($_.Exception.Message)"] -ForegroundColor Red -BackgroundColor DarkBlue
    
}

The exception was caught, and the code in the Catch block was executed.

Now let’s try this…

Try {
    
    Get-ChildItem -Path Z: -ErrorAction Stop
    Get-ThisWontWork

}

Catch [System.Management.Automation.CommandNotFoundException] {
    
    Write-Host "Command not found!"`n -ForegroundColor Red 
    Write-Host "Message: [$($_.Exception.Message)"] -ForegroundColor Red -BackgroundColor DarkBlue
    
}

Ahh! An error that wasn’t handled! Luckily we can add multiple catch blocks.

Let’s add another Catch block.

Catch {

Write-Host $_.Exception.Message

}
Try {
    
    Get-ChildItem -Path Z: -ErrorAction Stop
    Get-ThisWontWork

}

Catch [System.Management.Automation.CommandNotFoundException] {
    
    Write-Host "Command not found!"`n -ForegroundColor Red 
    Write-Host "Message: [$($_.Exception.Message)"] -ForegroundColor Red -BackgroundColor DarkBlue
    
}


Catch {

   Write-Host $_.Exception.Message

}

Now the exception from Get-ChildItem command is caught since the catch-all Catch block code is executed.

Getting Error Information

It can be handy to have a shortcut that shows you error information, which you can use to create specific Catch blocks. To do this, I created a function that I call in the Catch block which utilizes some validation itself! Here is the function:

function Get-ErrorInformation {
    [cmdletbinding()]
    param($incomingError)

    if ($incomingError -and (($incomingError| Get-Member | Select-Object -ExpandProperty TypeName -Unique) -eq 'System.Management.Automation.ErrorRecord')) {

        Write-Host `n"Error information:"`n
        Write-Host `t"Exception type for catch: [$($IncomingError.Exception | Get-Member | Select-Object -ExpandProperty TypeName -Unique)]"`n 

        if ($incomingError.InvocationInfo.Line) {
        
            Write-Host `t"Command                 : [$($incomingError.InvocationInfo.Line.Trim())]"
        
        } else {

            Write-Host `t"Unable to get command information! Multiple catch blocks can do this :("`n

        }

        Write-Host `t"Exception               : [$($incomingError.Exception.Message)]"`n
        Write-Host `t"Target Object           : [$($incomingError.TargetObject)]"`n
    
    }

    Else {

        Write-Host "Please include a valid error record when using this function!" -ForegroundColor Red -BackgroundColor DarkBlue

    }

}

Here is the full code I’ll be running for this example:

function Get-ErrorInformation {
    [cmdletbinding()]
    param($incomingError)

    if ($incomingError -and (($incomingError| Get-Member | Select-Object -ExpandProperty TypeName -Unique) -eq 'System.Management.Automation.ErrorRecord')) {

        Write-Host `n"Error information:"`n
        Write-Host `t"Exception type for catch: [$($IncomingError.Exception | Get-Member | Select-Object -ExpandProperty TypeName -Unique)]"`n 

        if ($incomingError.InvocationInfo.Line) {
        
            Write-Host `t"Command                 : [$($incomingError.InvocationInfo.Line.Trim())]"
        
        } else {

            Write-Host `t"Unable to get command information! Multiple catch blocks can do this :("`n

        }

        Write-Host `t"Exception               : [$($incomingError.Exception.Message)]"`n
        Write-Host `t"Target Object           : [$($incomingError.TargetObject)]"`n
    
    }

    Else {

        Write-Host "Please include a valid error record when using this function!" -ForegroundColor Red -BackgroundColor DarkBlue

    }

}

Try {
   
    Get-ChildItem -Path Z: -ErrorAction Stop

    Get-ThisWontWork

}

Catch [System.Management.Automation.CommandNotFoundException] {

    Write-Host 'Command not found Catch block executed!' 

}

Catch {

   Get-ErrorInformation -incomingError $_

}

So now, if we wanted to catch this exception on it’s own, we would need to add a catch block for [System.Management.Automation.DriveNotFoundException].

Catch [System.Management.Automation.CommandNotFoundException] {

Write-Host 'Command not found Catch block executed!' 

}

Let’s add that to our code and run the following:

function Get-ErrorInformation {
    [cmdletbinding()]
    param($incomingError)

    if ($incomingError -and (($incomingError| Get-Member | Select-Object -ExpandProperty TypeName -Unique) -eq 'System.Management.Automation.ErrorRecord')) {

        Write-Host `n"Error information:"`n
        Write-Host `t"Exception type for catch: [$($IncomingError.Exception | Get-Member | Select-Object -ExpandProperty TypeName -Unique)]"`n 

        if ($incomingError.InvocationInfo.Line) {
        
            Write-Host `t"Command                 : [$($incomingError.InvocationInfo.Line.Trim())]"
        
        } else {

            Write-Host `t"Unable to get command information! Multiple catch blocks can do this :("`n

        }

        Write-Host `t"Exception               : [$($incomingError.Exception.Message)]"`n
        Write-Host `t"Target Object           : [$($incomingError.TargetObject)]"`n
    
    }

    Else {

        Write-Host "Please include a valid error record when using this function!" -ForegroundColor Red -BackgroundColor DarkBlue

    }

}

Try {
   
    Get-ChildItem -Path Z: -ErrorAction Stop

    Get-ThisWontWork

}

Catch [System.Management.Automation.CommandNotFoundException] {

    Write-Host 'Command not found Catch block executed!' 

}

Catch [System.Management.Automation.DriveNotFoundException] {

    Write-Host 'Get-ChildItem drive not found Catch block executed!'

}

Catch {

   Get-ErrorInformation -incomingError $_

}

There we go! Now all our errors are handled, minus the ones we don’t know about yet.

Homework

  • Figure out why when multiple Catch blocks are used, it doesn’t pass along the execution information (unable to get command/line).

    • Let me know why this is!

  • Where else could I have added error handling in any of these examples?

I hope you’ve enjoyed the series so far! As always, leave a comment if you have any feedback or questions!

-Ginger Ninja

[Back to Top]

Hey there!

We often come across Error codes (or Exit Codes) in windows operating system environment, but most of the time we’re unsure what these numerical values actually mean, unless we try Googling it out the number.

WHAT IS ERROR EXIT CODE ?

The Exit code or Return code or System Error code of a process in computer programming is a small number passed from a child process (or CALLEE) to a parent process (or CALLER) when it has finished executing a specific procedure or delegated task.

Windows uses 32-bit signed integers as exit codes.If a process fails initialization, a Windows system error code may be returned

So, in order to decipher these numbers,  I wrote two PowerShell functions  –

  1. Import-WindowsErrorCode : To import all these error Code information from series of MSDN URL’s mention HERE
  2. Get-WindowsErrorCodeInfo : To query the information of a specific Error Code from imported data..

PURPOSE : 

  1. Quickly lookup for Error description depending upon the Windows Error Code/ Exit Code passed.
  2. Adding some verbosity to plain simple Error/Exit Codes.
  3. Could be utilized for a better Error Handling and better Investigation and Analysis.

Like in the below screenshot I passed the exit code returned while installing a .MSI file to the function Get-WindowsErrorCodeInfo to get information like ErrorString, Description and corresponding Hexa-Decimal value

purpose

Similarly, more information can be queried from the Error codes generated by running .exe or .MSU files, like in below image.

purpose2

IMPORTING/SAVING SYSTEM ERROR INFORMATION :

Run the below mentioned function from a Powershell console and it will make web Queries to Microsoft MSDN Web sites to capture all error codes, like in the following screenshot.

Its nothing but a series of Invoke-WebRequest’s on MSDN URL’s to web scrap the error code information, Sort them and make them in presentable format, which could be easily parsed.

importing

Now you can either convert and Save the results locally in a JSON file (You can also choose CSV) ,

Or, convert it to JSON , then COPY the result

howtosave

and upload it to your Github Gist.

gist

HOW TO RUN IT : 

Get the script from HERE on my Github Repository and you can run the Import-WindowsErrorCode function to save the information and then Get-WindowsErrorCode to query the error codes.

Following are some ways to Query information using the Error/Exit Codes

  1. You can query single exit code or can pass multiple value through Pipeline.
    By default it queries my Github Gist available over internet.
    1
  2. You can also query the exit code information from a local JSON file.
    2
  3. Or you can dump the JSON data on your Github Gist and retrieve the exit code information like below, by passing your URL under -GitHubJSONUrl switch
    3
  4. In case you don’t mention any specific exit code or path; The function will return all exit code available from my Github gist, which I would advise to be the preferable method. Which will fetch around 2700 Exit Codes2764

NOTE : 

You can skip the importing part and directly use the Get-WindowsErrorCodeInfo function which will query my Github gist URL by default ( but Requires Internet Connectivity).

I’ve taken care of the importing part for you guys 🙂 by importing and saving the all Windows System Error codes on my public Github gist.


Updated on 21 July  :

From few comments on Reddit link sharing, I’ve learned that this may not be the smartest way to get the error code description. You can also use windows Native command (Net Helpmsg Errorcode) to get the description which uses native windows API to get this information.

native

but after some hit and trial I’ve found that this approach has some limitations and doesn’t identifies every exit code we fetched form Microsoft websites. Like in the example in following screenshot for ERROR_INTERNET_* type error messages

native

I think both approaches are good and there is a trade-off between Speed and More information. Choice is yours!


Hoping you find it useful in your day to day work, comment and let me know for any improvements! Happy Learning 🙂

@SinghPrateik

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!

Понравилась статья? Поделить с друзьями:
  • Postgresql как изменить пароль пользователя postgres
  • Postgresql как изменить название столбца
  • Postgresql как изменить имя базы данных
  • Postgresql как изменить владельца таблицы
  • Postgresql there has been an error