forked from jdhitsolutions/ISEScriptingGeek
-
Notifications
You must be signed in to change notification settings - Fork 0
/
about_Scripting_Try_Catch.help.txt
118 lines (93 loc) · 8.48 KB
/
about_Scripting_Try_Catch.help.txt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
TOPIC
about_Scripting_Try_Catch
SHORT DESCRIPTION
A tutorial and suggestions on using Try/Catch.
LONG DESCRIPTION
I see a lot of scripts that people write so I’d include a short guide on
how to properly use Try/Catch. This is the way I think it should be used.
Let’s start with a Try/Catch block that might look ok at first glance.
Try {
Get-Service Foo
}
Catch {
Write-Warning "Oops"
Write-Warning $_.Exception.Message
}
You might expect that if the service FOO can’t be found that the code in
the Catch script block will run.
PS C:\work> .\trydemo.ps1
Get-Service : Cannot find any service with service name 'Foo'.
At C:\work\trydemo.ps1:4 char:14
+ Get-Service <<<< Foo
+ CategoryInfo : ObjectNotFound: (Foo:String) [Get-Service],
ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.Power
Shell.Commands.GetServiceCommand
Nope. I got an exception, but my code in the Catch script block did not
run. You can only catch *terminating* exceptions. In order for Try/Catch
to work properly, I have to make sure that if there is an exception, that
it gets treated as a terminating exception.
The best way is to use the common -ErrorAction parameter and set it to
Stop. Usually this is done on a per cmdlet basis.
Try {
Get-Service Foo -ErrorAction Stop
}
Catch {
Write-Warning "Oops"
Write-Warning $_.Exception.Message
}
The parameter has an alias of -ea which you’ll often see used. Now let’s
see what happens:
PS C:\work> .\trydemo.ps1
WARNING: Oops
WARNING: Cannot find any service with service name 'Foo'.
PS C:\work>
That’s what I was expecting. The exception was detected and treated as a
terminating exception which was caught by the Catch scriptblock. The $_
in the Catch scriptblock is the exception object.
Now for the tricky part. Look at this variation.
Try {
Get-Service -ComputerName Bogus
}
Catch {
Write-Warning "Oops"
Write-Warning $_.Exception.Message
}
What happens when I run this?
PS C:\work> .\trydemo.ps1
WARNING: Oops
WARNING: Cannot open Service Control Manager on computer 'Bogus'. This
operation might require other privileges.
How about that? Even without -erroraction, my catch code still ran. Based
on this I can safely deduce that the remote connection failure auto-
matically created a terminating exception. So the fact that I didn't have
-ErrorAction Stop was irrelevant.
But without a lot of trial and error or experience, I think it is extremely
difficult to know in advance what type of error will throw a terminating
exception and what won’t. Personally, I think the best approach is to
always use -ErrorAction stop on a cmdlet in a Try scriptblock to guarantee
you will always get a terminating exception.
Finally, depending on your needs you might have a single Try/Catch that
handles multiple commands. If so, you can set the ErrorActionPreference
at the scope level.
Try {
$ErrorActionPreference='Stop'
$comp = "SERVER01"
Write-Host "Getting Process data" -foreground Green
$p = Get-Process svchost -computername $comp
Write-Host "Getting Service data" -foreground Green
$s = Get-Service -computername $comp | where {$_.status -eq 'Running'}
Write-Host "Getting OS data" -foreground Green
$w = Get-WMIObject win32_operatingsystem -computername $comp
}
Catch {
Write-Warning "There was a problem gathering data"
Write-Warning $_.Exception.message
}
If any of the commands in the Try scriptblock encounter and error, they
will be treated as terminating exceptions and code in the Catch scriptblock
will run. Also note that if there is a terminating exception in one command
subsequent commands will not be run and PowerShell will move on to whatever
is after the Catch scriptblock.
SEE ALSO
about_Try_Catch_Finally