Learn about Windows PowerShell
Hey, Scripting Guy! I enjoyed reading your blog post yesterday about using $ErrorActionPreference to control the behavior of a script. One thing I never liked about using “On Error Resume Next” from VBScript was that it seemed to be an all-or-nothing type of proposition. There are certain errors I do not need to see, but then again, there are some errors I definitely must see. Is there another approach I can take to using $ErrorActionPreference?
Microsoft Scripting Guy Ed Wilson here. Today has been a crazy day, and it will continue being crazy until into the night. I am between meetings right now. I did a Live Meeting presentation to the Oklahoma City Developers Group this morning, and I will have another presentation this evening. Immediately after I finished this morning’s presentation, Craig and I had a conference call with a group inside Microsoft that is investigating reaching out to the community, and they wanted to talk to The Scripting Guys. In addition to the three presentations today, two other meetings canceled. One problem with canceled meetings is they have a way of cropping back up on your calendar. I am taking advantage of one of those canceled meetings to check the email@example.com e-mail account.
One of the cool things you can do with Windows PowerShell is use the –ErrorAction parameter. It is one of the standard parameters, and is therefore available on all cmdlets. This allows you to specify a custom error action for each cmdlet or each line of code in your script. In the code seen here, the first line of code informs you of an error if it occurs while retrieving the content of the c:\fso\computers.txt file. If an error occurs, after informing you of the problem, the script continues to the next line. The erroraction for the second line of code is stop. The script will halt if the Get-Content cmdlet is unable to find foo. This is shown here:
Get-Content -ErrorAction continue -Path C:\fso\Computers.txtGet-Content -ErrorAction stop -Path foo
When the script runs, the output appears that is shown in the following image.
The –ErrorAction parameter works in exactly the same manner as the $ErrorActionPreference automatic variable. The $ErrorActionPreference automatic variable was discussed in yesterday’s Hey, Scripting Guy! Blog post.
If you are working interactively from within the Windows PowerShell console, you might not want to type –ErrorAction every time you wish to specify a different error action level. Even with tab expansion, it can be a bit annoying. To work around that problem, you can use the parameter alias, ea, as shown here:
PS C:\> Get-WmiObject -Class win32_bios -EA silentlyContinueSMBIOSBIOSVersion : A05Manufacturer : Dell Inc.Name : Phoenix ROM BIOS PLUS Version 1.10 A05SerialNumber : BDY91L1Version : DELL - 15PS C:\>
With tab expansion, the big problem is not typing the –ErrorAction parameter name, but supplying the value for the parameter. One thing to keep in mind is that the –ErrorAction parameter expects a string, and therefore you do not have to supply the value inside quotation marks. You can leave out the quotation marks, and it works just fine. Of course, if you forget and put them in, it does not affect the outcome. This is shown here:
PS C:\> Get-WmiObject -Class win32_bios -EA "silentlyContinue"SMBIOSBIOSVersion : A05Manufacturer : Dell Inc.Name : Phoenix ROM BIOS PLUS Version 1.10 A05SerialNumber : BDY91L1Version : DELL - 15PS C:\>
On the other hand, you must spell the parameter correctly. If you do not, the error that is generated will tell you the allowable parameters. This is shown here:
PS C:\> Get-WmiObject -Class win32_bios -EA silentlyContinueeGet-WmiObject : Cannot bind parameter 'ErrorAction'. Cannot convert value "silentlyContinuee" to type "System.Management.Automation.ActionPreference" due to invalid enumeration values. Specify one of the following enumeration values and try again. The possible enumeration values are "SilentlyContinue, Stop, Continue, Inquire".At line:1 char:36+ Get-WmiObject -Class win32_bios -EA <<<< silentlyContinuee + CategoryInfo : InvalidArgument: (:) [Get-WmiObject], ParameterBindingException + FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.GetWmiObjectCommand
Notice that the error message tells you the allowed enumeration values: SilentlyContinue, Stop, Continue, and Inquire. The values you can supply for the –ErrorAction parameter are members of the System.Management.Automation.ActionPreference .NET Framework class. The enumeration and association values are seen in Table 1.
The Windows PowerShell runtime will continue processing without notifying the user that an action has occurred.
The Windows PowerShell runtime will stop processing when an action occurs.
The Windows PowerShell runtime will continue processing and notify the user that an action has occurred.
The Windows PowerShell runtime will stop processing and ask the user how it should proceed.
An old post on the Windows PowerShell team blog indicates you can use the enumeration values directly. This is a great solution when trying to type short commands from the Windows PowerShell console. Using the alias gc for Get-Content, leaving out the positional argument path, and using the alias ea for the –ErrorAction parameter, and the enumeration value 0 for SilentlyContinue results in a very short command. This example is shown here:
PS C:\> gc foo -ea 0PS C:\>
If you want to have the command inquire about the action, use the –ErrorAction enumeration value of 3 as shown here:
PS C:\> gc foo -ea 3ConfirmCannot find path 'C:\foo' because it does not exist.[Y] Yes [A] Yes to All [H] Halt Command [S] Suspend [?] Help (default is "Y"): yGet-Content : Cannot find path 'C:\foo' because it does not exist.At line:1 char:3+ gc <<<< foo -ea 3 + CategoryInfo : ObjectNotFound: (C:\foo:String) [Get-Content], ItemNotFoundException + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommandPS C:\>
When writing a script, I do not recommend using aliases and enumeration values directly because it makes the script very difficult to read, which in turn makes the script harder to troubleshoot. However, when working interactively from the Windows PowerShell prompt, it is perfectly acceptable to use the enumeration values. In fact, you can also use partial parameters as well, as long as you type enough of the parameter name to make it unique. In the example seen here, where –com is used for the –computer parameter, gwmi is an alias for the Get-WmiObject cmdlet, and –ea is the parameter alias for –ErrorAction. The enumeration value of 3 translates to inquire. When the cmdlet fails to connect to a remote computer named win7-pc1, it prompts for the action to take place. I respond “h,” which means to halt execution. Windows PowerShell then displays a message that the command was halted at user request. This is shown here:
PS C:\> gwmi win32_bios -com win7-pc1 -ea 3ConfirmThe RPC server is unavailable. (Exception from HRESULT: 0x800706BA)[Y] Yes [A] Yes to All [H] Halt Command [S] Suspend [?] Help (default is "Y"): hGet-WmiObject : Command execution stopped because the user selected the Halt option.At line:1 char:5+ gwmi <<<< win32_bios -com win7-pc1 -ea 3 + CategoryInfo : OperationStopped: (:) [Get-WmiObject], ParentContainsErrorRecordException + FullyQualifiedErrorId : ActionPreferenceStop,Microsoft.PowerShell.Commands.GetWmiObjectCommandPS C:\>
TS, that is all there is to using the –ErrorAction preference parameter. Error Handling Week will continue tomorrow when we will talk about…wait a minute.
If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at firstname.lastname@example.org or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.
Ed Wilson and Craig Liebendorfer, Scripting Guys