Force a full domain name in param - powershell

param(
[Parameter(Mandatory = $true , HelpMessage = "Enter a domain like facebook.com")]
[ValidateScript({
try {
$_ -like "*.*"
}
catch {
throw "Enter a domain like facebook.com."
}
})][string]$Domain
)
I am trying to learn to error check in param. I know how to do this in a if .
From what I read this should work but when sent Facebook I get the error below.
It works for facebook.com
error
Cannot validate argument on parameter 'Domain'. The "
try {
$_ -like "*.*"
}
catch {
throw "Enter a domain like facebook.com."
}
" validation script for the argument with value "facebook" did not return a result of True. Determine why the validation script failed,
and then try the command again.
At line:1 char:1
+ . {
+ ~~~
+ CategoryInfo : InvalidData: (:) [], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError
What am I doing wrong?

Your current try statement will not throw an error, so it will never run catch. You could also throw a better error type
Your validation script should look closer to this:
param(
[ValidateScript({
if ($_ -like "*.*") {
$true
}
else {
Throw [System.Management.Automation.ValidationMetadataException] "Enter a domain like facebook.com."
}
})][string]$Domain
)
You can use try/catch in validation scripts, but only if the actual try block returns an error

You can use ValidatePattern with regex
[ValidatePattern('.*\..*')]
In Powershell 7 the ErrorMessage parameter was added
[ValidatePattern('.*\..*', ErrorMessage = "your message")]

Related

Why can I not catch my non-terminating error?

I'd like to show someone an example on how to catch non terminating errors in PowerShell.
I created this function:
# This will write a non-terminating error
function NonTerminatingErrorExample {
Param($i = 5)
if ($i -gt 4) {
Write-Error "I expected a value less or equal to 4!"
}
Write-Host "However, I can still continue the execution"
}
However, I can't catch it with -ErrorAction Stop
Try {
NonTerminatingErrorExample -ErrorAction Stop
} Catch {
Write-Host "Now you see this message."
}
I never get the catch block returned. Why?
NonTerminatingErrorExample : I expected a value less or equal to 4!
In Zeile:32 Zeichen:5
+ NonTerminatingErrorExample -ErrorAction Stop
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,NonTerminatingErrorExample
However, I can still continue the execution
Your function isn't a cmdlet and therefore doesn't support -ErrorAction. Add [CmdletBinding()] to the body to make it one and the parameter will be supported. You can see the difference if you Get-Help both versions: as a function, there is no [<CommonParameters>].

Powershell catching exception type

Is there a convenient way to catch types of exceptions and inner exceptions for try-catch purposes?
Example code:
$a = 5
$b = Read-Host "Enter number"
$c = $a / $b #error if $b -eq 0
$d = get-content C:\I\Do\Not\Exist
Row #3 will generate a runtime error with an inner exception (EDIT: fixed this command $Error[1].Exception.InnerException.GetType()), row #4 will generate a "standard"(?) type of exception ($Error[0].Exception.GetType()).
Is it possible to get the desired result from both of these with the same line of code?
Ad1: error from row 3
At -path-:3 char:1
+ $c = $a / $b #error if $b -eq 0
+ ~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
Ad2: error from row 4
get-content : Cannot find path 'C:\I\Do\Not\Exist' because it does not exist.
At -path-:4 char:6
+ $d = get-content C:\I\Do\Not\Exist
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (C:\I\Do\Not\Exist:String)
[Get-Content], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetContentCommand
Edit: To make it clear, I want the result to return DivideByZeroException and ItemNotFoundException in some way
First of all, you can explicitly catch specific exception types:
$ErrorActionPreference = "Stop"
try {
1 / 0
}
catch [System.DivideByZeroException] {
$_.Exception.GetType().Name
}
try {
Get-Item "c:\does-not-exist"
}
catch [System.Management.Automation.ItemNotFoundException] {
$_.Exception.GetType().Name
}
The DivideByZeroException is basically just the InnerException of RuntimeException, and theoretically, the InnerExceptions could be endlessly nested:
catch {
$exception = $_.Exception
do {
$exception.GetType().Name
$exception = $exception.InnerException
} while ($exception)
}
BUT you can handle RuntimeException as a special case. Even PowerShell does so. Look at the first code example. The catch-block is reached even though the type of the inner exception is specified.
You could do something similar yourself:
catch {
$exception = $_.Exception
if ($exception -is [System.Management.Automation.RuntimeException] -and $exception.InnerException) {
$exception = $exception.InnerException
}
$exception.GetType().Name
}
NOTE that you need one try-catch per command, if you want to catch both exceptions. Else the 2nd will not be executed if the 1st one fails. Also you have to specify $ErrorActionPreference to "Stop" to catch also non-terminating exceptions.
Are you trying to catch specific error types like this?
https://blogs.technet.microsoft.com/poshchap/2017/02/24/try-to-catch-error-exception-types/

PowerShell module not dot-sourcing / importing functions as expected

Update 1:
Originally, I posted this with the title: "Scripts ignoring error handling in PowerShell module" as that is the current issue, however it seems more of a module issue, so I have renamed the title.
Update 2:
After a comment that made me question Azure cmdlets, I've tested with the most basic of scripts (added to the module) and the findings are the same, in that the error is not passed to the calling script, however, adding -errorVariable to Get-Service does return something (other than WriteErrorException) that I could probably harness in the handling of the error:
function Test-MyError($Variable)
{
Try
{
Get-Service -Name $variable -ErrorAction Stop -ErrorVariable bar
#Get-AzureRmSubscription -SubscriptionName $variable -ErrorAction Stop
}
Catch
{
Write-Error $error[0]
$bar
}
}
returns:
Test-MyError "Foo"
Test-MyError : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:3 char:1
+ Test-MyError "Foo"
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-MyError
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Cannot find any service with service name 'foo'.
However, if I run "Test-MyError" in ISE, then call the function, I get:
Test-MyError "Foo"
Test-MyError : Cannot find any service with service name 'Foo'.
At line:3 char:1
+ Test-MyError "Foo"
+ ~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Test-MyError
The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: Cannot find any service with service name 'Foo'.
So I am not sure what is happening when running "Test-MyError" in ISE and calling it, against it being dot-sourced in the PSM1 file and then calling it?
Do I now have to use -ErrorVariable and handle on that?
Original Question:
I have two functions in a module: Get-Subscription and Get-AllSubscriptions. Each function sits in its own PS1 file and the PSM1 file dot-sources them. The module seems fine as the module scripts are accessible using intelisense and the module loads without issue. I've used this structure in many modules and I haven't come across this problem before. (Although I wonder if MS have changed the way modules work in PS 5.1 as I have noticed using FunctionsToExport='x','y','Z' and Export-ModuleMember don't seem to behave the same way as they used to.)
Get-AllSubscriptions calls Get-Subscription.
If I am not logged into Azure, Get-Subscription should throw an error which is handled, prompting me to log in. This works as expected, if I call Get-Subscription from the Get-Subscription.ps1.
However, when I call Get-Subscription from the a new PS1 file, Get-AllSubscriptions or from the powershell console, it doesn't work. It iterates all the way through the do..until loop, without "handling" the errors as I would expect. On each iteration, it seems to throw a generic error:
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
However, I do see the last error, Get-Subscription : Unable to find requested subscription after 3 login attempts.
If I execute Get-Subscription in ISE, then call Get-Subscription in a new PS1 file or from Get-AllSubscriptions, it works as expected, however, once I re-import the module (Import-Module AzureVnetTools -Force -Verbose), it goes back to the incorrect behaviour.
If I dot-source Get-Subscription, inside the caller script, it works, but why? This is what should happen with the module's PSM1.
Can anyone help me work out what I am doing wrong here?
(PS 5.1, Windows 7)
Get-Subscription:
function Get-Subscription
{
[cmdletbinding()]
Param
(
[string]$SubscriptionName,
[string]$UserName,
[string]$code
)
$c=1
Write-Verbose "Checking access to '$SubscriptionName' with user '$UserName'..."
Do
{
Write-Verbose "Attempt $c"
Try
{
$oSubscription = Get-AzureRmSubscription -SubscriptionName $SubscriptionName -ErrorAction Stop -WarningAction SilentlyContinue
Write-Verbose "Subscription found: $($oSubscription.SubscriptionName)."
}
Catch
{
if($error[0].Exception.Message -like "*Please verify that the subscription exists in this tenant*")
{
Write-Verbose "Cannot find subscription '$SubscriptionName' with provided credentials."
$account = Login-AzureRmAccount -Credential (Get-Credential -UserName $Username -Message "Subscription '$SubscriptionName' user' password:")
}
elseif($error[0].Exception.Message -like "*Run Login-AzureRmAccount to login*")
{
Write-Verbose "No logged in session found. Please log in."
$account = Login-AzureRmAccount -Credential (Get-Credential -UserName $Username -Message "Subscription '$SubscriptionName' user' password:")
}
else
{
Write-Error $error[0]
}
}
$c++
}
until(($oSubscription) -or ($c -eq 4))
if($c -eq 4)
{
Write-Error "Unable to find requested subscription after $($c-1) login attempts."
break
}
$oSubscription | Add-Member -MemberType NoteProperty -Name Code -Value $code
$oSubscription
}
Get-AllSubscriptions:
function Get-AllSubscriptions
{
[cmdletbinding()]
param
(
[string]$MasterSubscription,
[string]$MasterSubscriptionCode,
[string]$MasterSubscriptionUsername,
[string]$ChildSubscription,
[string]$ChildSubscriptionCode,
[string]$ChildSubscriptionUsername
)
Write-Verbose "Getting all subscriptions..."
$oAllSubscriptions = #()
$oMasterSubscription = Get-Subscription -SubscriptionName $MasterSubscription -UserName $MasterSubscriptionUsername -code $MasterSubscriptionCode -Verbose
$oChildSubscription = Get-Subscription -SubscriptionName $ChildSubscription -UserName $ChildSubscriptionUsername -code $ChildSubscriptionCode -Verbose
$oAllSubscriptions = ($oMasterSubscription,$oChildSubscription)
$oAllSubscriptions
}
Test:
$splat2 = #{
SubscriptionName = "SomeSubscription"
Code = "S02"
Username = "some.user#somewhere.com"
}
#Write-Output "Dot-source:"
#. "D:\Temp\PS.Modules\AzureVnetTools\functions\public\Get-Subscription.ps1"
Get-Subscription #splat2 -verbose
Output:
Get-Subscription #splat2 -verbose
VERBOSE: Checking access to 'SomeSubscription' with user 'some.user#somewhere.com'...
VERBOSE: Attempt 1
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:7 char:1
+ Get-Subscription #splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
VERBOSE: Attempt 2
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:7 char:1
+ Get-Subscription #splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
VERBOSE: Attempt 3
Get-Subscription : Exception of type 'Microsoft.PowerShell.Commands.WriteErrorException' was thrown.
At line:7 char:1
+ Get-Subscription #splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
Get-Subscription : Unable to find requested subscription after 3 login attempts.
At line:7 char:1
+ Get-Subscription #splat2 -verbose
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Subscription
AzureVnetTools.psm1
#Get public and private function definition files.
$Public = #( Get-ChildItem -Path $PSScriptRoot\Functions\Public\*.ps1 -ErrorAction SilentlyContinue )
$Private = #( Get-ChildItem -Path $PSScriptRoot\Functions\Private\*.ps1 -ErrorAction SilentlyContinue )
#Dot source the files
Foreach($import in #($Public + $Private))
{
#write-error $import.fullname
Try
{
#Write-Host "Dot-sourcing file: $($import.fullname)."
. $import.fullname
}
Catch
{
Write-Error -Message "Failed to import function $($import.fullname): $_"
}
}
Export-ModuleMember -Function $Public.Basename
AzureVnetTools.psd1 (Relevant section):
FunctionsToExport = '*'
-ErrorAction Stop -WarningAction SilentlyContinue
Is it a warning that's being thrown instead of an error?
So my specific problem was that I was relying on handling the error and doing something based on that. The problem was caused by the way PowerShell's Write-Error works (or not) as I learned from the reply here, given by #Alek.
It simply wasn't passing the actual error back to the calling script. As #Alex suggested, I replaced Write-Error with $PSCmdlet.WriteError(). Although this didn't totally work.
In the Catch{} block, I then changed $error[0] to $_ and the full error was returned to the calling script / function.
I went one further and wrote a reusable function, added to my module:
function Write-PsError
{
[cmdletbinding()]
Param
(
[Exception]$Message,
[Management.Automation.ErrorCategory]$ErrorCategory = "NotSpecified"
)
$arguments = #(
$Message
$null #errorid
[Management.Automation.ErrorCategory]::$ErrorCategory
$null
)
$ErrorRecord = New-Object -TypeName "Management.Automation.ErrorRecord" -ArgumentList $arguments
$PSCmdlet.WriteError($ErrorRecord)
}
Which seems to be working well at the moment. I especially like the way intellisense picks up all the ErrorCategories. Not sure what or how ISE (PS 5.1 / Win 7) does that. I thought I was going to have to add my own dynamic parameter.
HTH.

Powershell - simply checking if a function completed successfully or not (times out)

I basically have this simple powershell script that executes an ssrs report url and saves it to the network.
It usually runs fine, but sometimes it times out and when it does, it still says it succeeded. I've tried a handful of things with no luck.
A simplified version of my script looks like this:
-----------------------------
function RunReport($url,$outputfile) {
# // create a request
[Net.HttpWebRequest] $req = [Net.WebRequest]::create($url)
$req.Method = "GET"
$req.Timeout = 600000 # = 10 minutes
# // Set credentials
$req.UseDefaultCredentials = $true
#echo "Getting Response"
[Net.HttpWebResponse] $result = $req.GetResponse()
[IO.Stream] $stream = $result.GetResponseStream()
#[IO.StreamReader] $reader = New-Object IO.StreamReader($stream)
[System.IO.FileStream]$writeStream = New-Object System.IO.FileStream($outputfile, [System.IO.FileMode]::Create);
# // write to file
[byte[]]$buffer = new-object byte[] 4096
[int]$total = [int]$count = 0
do
{
$count = $stream.Read($buffer, 0, $buffer.Length)
$writeStream.Write($buffer, 0, $count)
} while ($count -gt 0)
$writeStream.Close()
#$stream.flush()
$stream.Close()
}
$url=...
$outputfile=...
IF(RunReport "$url" "$outputfile")
{Write-Host "Success"}
ELSE
{Write-Host "Failed"}
-------------------------------
I've tried stuff like this with no luck:
RunReport "$url" "$outputfile"
If($?)
{Write-Host "Success"}
ELSE
{Write-Host "Failed"}
and
RunReport "$url" "$outputfile"
If($? -eq true)
{Write-Host "Success"}
ELSE
{Write-Host "Failed"}
The timeout error I'm dealing with is:
Exception calling "GetResponse" with "0" argument(s): "The operation has timed out"
At C:\data\powershell\script.ps1:9 char:49
+ [Net.HttpWebResponse] $result = $req.GetResponse <<<< ()
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
You cannot call a method on a null-valued expression.
At C:\data\powershell\script.ps1:10 char:48
+ [IO.Stream] $stream = $result.GetResponseStream <<<< ()
+ CategoryInfo : InvalidOperation: (GetResponseStream:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\data\powershell\script.ps1:18 char:38
+ $count = $stream.Read <<<< ($buffer, 0, $buffer.Length)
+ CategoryInfo : InvalidOperation: (Read:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
You cannot call a method on a null-valued expression.
At C:\data\powershell\script.ps1:23 char:14
+ $stream.Close <<<< ()
+ CategoryInfo : InvalidOperation: (Close:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Any help would be greatly appreciated. I assume this should be fairly easy, just don't have the correct syntax ? Thanks
Maybe you can use try/catch to deal with that part like this:
try {
[Net.HttpWebResponse] $result = $req.GetResponse()
}
catch {
return 1
}
You can apply the same technique in other places where you suspect code is not doing what it is supposed to do like:
try {
[System.IO.FileStream]$writeStream = New-Object System.IO.FileStream($outputfile, [System.IO.FileMode]::Create);
}
catch {
return 1
}
Once you detect where the issue is happening, you could then look into exception like
catch { write-warning $_ ; exit 1 }
The 'cannot call a method on a null-valued expression' errors are all stemming from the fact that the .GetResponse method is failing with a timeout, leaving the $result variable unassigned. The simplest change would be to put the rest of the script (after "$result = $req.GetResponse()") into an "if ($result) {}" block. You can then use a "then {}" block to do your error handling.
A more advanced method would be to use try {} and catch {} blocks, to catch the actual timeout exception and handle it properly.
You have two problems:
The timeouts (and the cascading errors from that)
Your RunReport function doesn't ever return anything.
For #2, you can't test something that doesn't exist. So make your function return some kind of success/fail indicator to the caller.
For #1, when you call GetResponse() you need to wrap it in a try/catch block, catch the exception, and exit the function with the appropriate status returned to the caller.
You might want to look at this SO post about calling SSRS using SOAP methods as well.

Catching dynamic exception types in PowerShell

I'm working on a PowerShell library that automates some network management operations. Some of these operations have arbitrary delays, and each can fail in unique ways. To handle these delays gracefully, I'm creating a generic retry function that has three main purposes:
Execute an arbitrary command (with parameters)
If it fails in a recognized way, try it again, up to some limit
If it fails in an unexpected way, bail and report
The problem is item #2. I want to be able to specify the expected exception type for the command. How can I do this in PowerShell?
Here's my function:
Function Retry-Command {
[CmdletBinding()]
Param(
[Parameter(Mandatory=$True, Position=0)]
[String] $name,
[Parameter(Mandatory=$True, Position=1)]
[String] $scriptBlock,
[String[]] $argumentList,
[Int] $maxAttempts=3,
[Int] $retrySeconds=10,
[System.Exception] $retryException=[System.Management.Automation.RuntimeException]
)
$attempts = 1
$keepTrying = $True
$cmd = [ScriptBlock]::Create($scriptblock)
do {
try {
&$cmd #argumentList
$keepTrying = $False
Write-Verbose "Command [$commandName] succeeded after $attmpts attempts."
} catch [$retryException] {
$msg = "Command [$commandName] failed. Attempt $attempts of $maxAttempts."
Write-Verbose $msg;
if ($maxAttempts -gt $attempts) {
Write-Debug "Sleeping $retrySeconds"
Start-Sleep -Seconds $retrySeconds
} else {
$keepTrying = $False
Write-Debug "Reached $attempts attempts. Re-raising exception."
Throw $_.Exception
}
} catch [System.Exception] {
$keepTrying = $False
$msg = "Unexpected exception while executing command [$CommandName]: "
Write-Error $msg + $_.Exception.ToString()
Throw $_.Exception
} finally {
$attempts += 1
}
} while ($True -eq $keepTrying)
}
I call it like this:
$result = Retry-Command -Name = "Foo the bar" -ScriptBlock $cmd -ArgumentList $cmdArgs
But this is the result:
Retry-Command : Cannot process argument transformation on parameter 'retryException'.
Cannot convert the "System.Management.Automation.RuntimeException" value of type "System.RuntimeType" to type "System.Exception".
At Foo.ps1:111 char:11
+ $result = Retry-Command <<<< -Name "Foo the bar" -ScriptBlock $cmd -ArgumentList $cmdArgs
+ CategoryInfo : InvalidData: (:) [Retry-Command], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Retry-Command
This seems to be saying that the type of [System.Management.Automation.RuntimeException] is not itself a [System.Exception], but is instead a [System.RuntimeType] which makes sense.
So, how do I specify the type of the exception to be caught?
It's not possible to use a variable as a catch criteria, it has to be a type-object (or something), everything else gives you an error. A workaround would be something like this:
#You can get the name of the exception using the following (or .Name for just the short name)
#PS > $myerr.Exception.GetType().Fullname
#System.UnauthorizedAccessException
function test {
param(
#Validate that specified name is a class that inherits from System.Exception base class
[ValidateScript({[System.Exception].IsAssignableFrom([type]$_)})]
$ExceptionType
)
try {
#Test-script, Will throw UnauthorizedAccessException when not run as admin
(Get-Content C:\test.txt) | % { $_ -replace 'test','lol' } | Set-Content C:\test.txt
}
catch [System.Exception] {
#Check if exceptiontype is equal to the value specified in exceptiontype parameter
if($_.Exception.GetType() -eq ([type]$ExceptionType)) {
"Hello. You caught me"
} else {
"Uncaught stuff: $($_.Exception.Gettype())"
}
}
}
A few tests. One with non-existing type, then with non-exception type, and finally a working one
PS > test -ExceptionType system.unaut
test : Cannot validate argument on parameter 'ExceptionType'. Cannot convert the "system.unaut" val
ue of type "System.String" to type "System.Type".
At line:1 char:21
+ test -ExceptionType system.unaut
+ ~~~~~~~~~~~~
+ CategoryInfo : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,test
PS > test -ExceptionType String
test : Cannot validate argument on parameter 'ExceptionType'. The "[System.Exception].IsAssignableF
rom([type]$_)" validation script for the argument with value "String" did not return true. Determin
e why the validation script failed and then try the command again.
At line:1 char:21
+ test -ExceptionType String
+ ~~~~~~
+ CategoryInfo : InvalidData: (:) [test], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,test
PS > test -ExceptionType UnauthorizedAccessException
Hello. You caught me