ErrorAction "SilentlyContinue" does not populate ErrorVariable - powershell

Issue
When using -ErrorAction "SilentlyContinue", the error variable is not being populated as described in the following documentation: Handling Errors the PowerShell Way.
Question
How to prevent the error to be displayed as it is with -ErrorAction "Continue" yet still populate the error variable?
Bonus question
Is there a way to append the error to the error variable in order to store more than one of them?
MWE
Script
$ErrorActions = #("Continue", "SilentlyContinue", "Stop")
foreach ($ErrorAction in $ErrorActions) {
Write-Host -Object $ErrorAction -ForegroundColor "Green"
Get-Item -Path "C:\tmp\error1" -ErrorAction $ErrorAction -ErrorVariable "ErrorMessage"
Get-Item -Path "C:\tmp\error2" -ErrorAction $ErrorAction -ErrorVariable "ErrorMessage"
Write-Host -Object "ErrorVariable" -ForegroundColor "Yellow"
$ErrorMessage
}
Output
Continue
Get-Item : Cannot find path 'C:\tmp\error1' because it does not exist.
At C:\tmp\mwe.ps1:43 char:5
Get-Item -Path "C:\tmp\error1" -ErrorAction $ErrorAction -ErrorVa ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\tmp\error1:String) [Get-Item], ItemNotFoundException
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
Get-Item : Cannot find path 'C:\tmp\error2' because it does not exist.
At C:\tmp\mwe.ps1:44 char:5
Get-Item -Path "C:\tmp\error2" -ErrorAction $ErrorAction -ErrorVa ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\tmp\error2:String) [Get-Item], ItemNotFoundException
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
ErrorVariable
Get-Item : Cannot find path 'C:\tmp\error2' because it does not exist.
At C:\tmp\mwe.ps1:44 char:5
Get-Item -Path "C:\tmp\error2" -ErrorAction $ErrorAction -ErrorVa ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\tmp\error2:String) [Get-Item], ItemNotFoundException
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand
SilentlyContinue
ErrorVariable
Stop
Get-Item : Cannot find path 'C:\tmp\error1' because it does not exist.
At C:\tmp\mwe.ps1:43 char:5
Get-Item -Path "C:\tmp\error1" -ErrorAction $ErrorAction -ErrorVa ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CategoryInfo : ObjectNotFound: (C:\tmp\error1:String) [Get-Item], ItemNotFoundException
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand

Using Get-ChildItem as an example:
Get-ChildItem C:\nonexist -EA SilentlyContinue -EV silentErr
[bool]$silentErr # ==> True
As the documentation you linked to mentions, for -ErrorVariable and $ErrorActionPreference controls the following behavior when non-terminating errors occur (these do not affect terminating errors):
Continue: Display the error and continue execution.
SilentlyContinue: Hide error but still add it to the -ErrorVariable, if specified, and $error stack.
Stop: Throws an exception and halts execution. Exceptions may be caught and handled via a try / catch / finally block.
Non-terminating errors cannot be normally handled via try / catch / finally because an exception isn't thrown unless -ErrorAction is Stop.
Ignore: The error is swallowed with no indication it occurred. Neither -ErrorVariable or the $error stack is updated in this case.
Inquire: Ask the operator what to do if an error occurs.
Using the above knowledge, we can still rely on the $error automatic variable and the specified-ErrorVariable to be populated if the -ErrorAction is SilentlyContinue.
Note: You can also use the $ErrorView variable to further control how errors are displayed in the console.
To answer your sub-question, there is not a mechanism for giving a "named" error stack, but you can use the built-in $error stack to keep track of the errors which occur (and didn't occur under-EA Ignore). If you want to ensure you only have errors that occur at a certain point onward in your script/session/etc, you can call the following to clear the error variable:
$error.Clear()
Additional Information
Terminating Errors
Non-Terminating Errors
$ErrorActionPreference preference variable
$Error and $ErrorView automatic variables

Related

Suppressing error messages in PowerShell ErrorVariable

Using the snippet below, I'm trying to find a way to suppress the "Attempted to divide by zero" error, and be left with just the custom error message in $err. I've tried combinations of try/catch, Invoke-Command/Expression, redirecting 2>$null, but in every case the error stream still contains the "attempted to divide by zero" message.
function func1 {
[CmdletBinding()]
param()
func2 -ErrorAction SilentlyContinue -ErrorVariable er
if ($er.Count -ge 1) {
Write-Error -Message "Custom error message!"
}
}
function func2 {
[CmdletBinding()]
param()
1/0
}
func1 -ErrorAction SilentlyContinue -ErrorVariable err
$err
populates $err with two items:
Attempted to divide by zero.
At line:15 char:3
+ 1/0
+ ~~~
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
func1 : Custom error message!
At line:18 char:1
+ func1 -ErrorAction SilentlyContinue -ErrorVariable err
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,func1
Thanks so much for your thoughts!
Unfortunately the solution is somewhat tricky, because the error that occurs in func2 is invariably recorded in the $err variable passed to -ErrorVariable in the func1 invocation, and is already stored there when the func2 call returns.
Therefore you need to manually remove it:
Replace:
if ($er.Count -ge 1) {
Write-Error -Message "Custom error message!"
}
with:
if ($er.Count -ge 1) {
if ($PSBoundParameters.ContainsKey('ErrorVariable')) {
# Remove the most recently added error from the $err variable.
$PSCmdlet.GetVariableValue($PSBoundParameters['ErrorVariable']).RemoveAt(0)
}
Write-Error -Message "Custom error message!"
}
The automatic $PSBoundParameters variable allows you to check if the common -ErrorAction parameter was specified and with what value (i.e., what target variable name).
The automatic $PSCmdlet variable's .GetVariableValue() method allows access to variables defined in the caller's scope, which enables retrieving the target variable value, which is a [System.Collections.ArrayList] instance whose .RemoveAt() method can be called to remove the most recently added error, which is at index 0.
Asides:
1/0 causes a statement-terminating error, whereas the common -ErrorAction parameter only acts on non-terminating errors (to catch terminating errors you need try / catch). However, because this statement-terminating error occurs inside a function, execution inside that function (potentially) continues, and to the caller the error is in effect a non-terminating one.
For a comprehensive overview of PowerShell's bewilderingly complex error handling, see GitHub docs issue #1583.

PowerShell Try Catch error handling function doesn't show my custom warning message [duplicate]

This question already has an answer here:
How to handle failed variable assignments in powershell? [duplicate]
(1 answer)
Closed 3 years ago.
I am trying to write a simple PowerShell code to create a registry key, then use TRY and CATCH to handle/catch any potential exceptions that may occur. As a test scenario, I am expecting to get "Script failed to create the registry key" if I modify the registry path. Unfortunately, the TRY/CATCH error handling function doesn't work for me and except the error itself nothing shows up in the console.
$NetBTpath = "HKLM:\System\CurrentControlSet\Services\NetBT\Parameters"
$RegValueName = "NodeType"
Try
{
if (((Get-ItemProperty $NetBTpath).PSobject.Properties.Name -contains $RegValueName) -ne "True")
{
New-ItemProperty -Path $NetBTpath -Name "NodeType" -Value 2 -PropertyType "dword"
}
}
Catch [System.Exception]
{
Write-warning "Script failed to create the registry key"
}
It works fine as long as the registry path is correct but if I rename the registry folder ...\NetBT\Parameters to ...\NetBT\Parameters1, I would only see:
Get-ItemProperty : Cannot find path 'HKLM:\System\CurrentControlSet\Services\NetBT\Parameters' because it does not exist.
At C:\temp\NetBT_RegConfig222.ps1:10 char:11
+ if (((Get-ItemProperty $NetBTpath).PSobject.Properties.Name -cont ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKLM:\System\Cu...etBT\Parameters:String) [Get-ItemProperty], ItemNotFoundExcep
tion
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemPropertyCommand
New-ItemProperty : Cannot find path 'HKLM:\System\CurrentControlSet\Services\NetBT\Parameters' because it does not exist.
At C:\temp\NetBT_RegConfig222.ps1:12 char:9
+ New-ItemProperty -Path $NetBTpath -Name "NodeType" -Value 2 ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (HKLM:\System\Cu...etBT\Parameters:String) [New-ItemProperty], ItemNotFoundExcep
tion
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.NewItemPropertyCommand
I have already tried to use only Catch {} as well as Catch [System.Management.Automation.ItemNotFoundException].
Please advice.
You need to add the -ErrorAction Stop switch to your Get-ItemProperty and New-ItemProperty lines. Sometimes commands will throw a non-fatal error, and the catch doesn't get invoked. To ensure that you will fall into your catch, add the above switch.

PowerShell Start-Service - Unable to validate 'InputObject' issue

Problem
This is semi-related to: PowerShell Start-Service Timeout
I am trying to run through a loop to enforce timeout of the action, but continue to run into a random validation error. The code is setup as such:
$timeout = New-TimeSpan -Seconds $SecondsToWait
$timer = [System.Diagnostics.Stopwatch]::StartNew()
$j = Start-Job -ScriptBlock { Start-Service $ServiceName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue }
$count = 0
Do {
If ($j.State -eq 'Running') {
If ($timer.Elapsed.seconds -ne $count) {
$count ++
Write-Host "Elapsed Time: $($timer.Elapsed.seconds)"
}
$j | Receive-Job
}
} While ( $timer.Elapsed -lt $timeout )
I have tried a view variations in attempts to resolve this, but I keep returning to the same root problem with the program exiting with
Cannot validate argument on parameter 'InputObject'. The Argument is null or empty.
Supply an argument that is not null or empty and then try the command again.
At C:file\path.ps1:543 char:13
$j | Receive-Job
CategoryInfo : InvalidData: (:) [Start-Service], ParameterBindingValidationException
FullyQualifiedErrorId: ParameterArgumentValidatinErrorNullNotAllowed,Microsoft.PowerShell.Commands.StartServiceCommand
I have looked through a number of solutions already on StackOverflow and a few other sites, but most are not similar enough to convert the answer to my problem. Most of the questions that I have seen pertain to the Invoke-Command feature of PowerShell or the issues is with a different command altogether. below is a small list of places I have sought out an answer:
powershell Start-Service fails
Powershell function throwing null exception
"Cannot validate argument on parameter 'Identity'" while changing the description for multiple users
Question
Has anyone run into this situation before and know how to resolve it? Also, before anyone says "oh you are not passing in anything during the Start-Service ", the Do While loop iterates randomly between 15 and 30 times before this error is encountered.
So receive-job gets the results of a thread. Then it deleted those results. The error you are getting is becuase the thread completed and the results are the error of
Start-Service $ServiceName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue
which is
Cannot validate argument on parameter 'InputObject'. The argument is
null or empty. Provide an argument that is not null or empty, and then
try the command again.
+ CategoryInfo : InvalidData: (:) [Start-Service], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartServiceCommand
+ PSComputerName : localhost
Becuase you didnt specify $ServiceName...
you can verify this by doing the following using -keep tag and remove the -keep tag. The -keep tag will tell the job not to delete the results till next call.
$j = Start-Job -ScriptBlock { Start-Service $ServiceName -ErrorAction SilentlyContinue -WarningAction SilentlyContinue }
$count = 0
Do {
$j.State
$j | Receive-Job -keep
} While ( $timer.Elapsed -lt $timeout )
the following will show running many time and then once completed will show the following
Running
Running
Running
Completed
Cannot validate argument on parameter 'InputObject'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.
+ CategoryInfo : InvalidData: (:) [Start-Service], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartServiceCommand
+ PSComputerName : localhost
it will keep repeating that error over and over until loop is finished OR until it hits a Receive-Job without a -keep
Sometimes it will show
Running
{Results here}
Running
{Results here}
Complete
{Results here}
This is because Receive-job is giving you faster information then System is updating the Thread.state to Completed.
IF you dont want to see that error then just delete Receive-Job or use a try catch for the error in the scriptblock

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.

Trap remove-item exception

In powershell there is some exception that I am not able to trap or I am not doing to correct things.
So here is the code that does the things:
log "Processing $($_.Name).old" $logFile
if (Test-Path "$($_.Name).old" )
{
& {
rm "$($_.Name).old"
}
trap #[System.UnauthorizedAccessException]
{
log "Move to trash" $logFile
moveTrach "$($_.Name).old"
continue
}
}
I had comment out the type in the trap expression to be sure to catch anything.
But unfortunately I never go into the trap clause.
I can see the exception log but not the "Move to trash" log.
2012-02-16 10:35:31 Processing file.dll
Remove-Item : Cannot remove item file.dll.old: Access to the path 'file.dll.old' is denied.
At upgradegw.ps1:189 char:29
+ rm <<<< "$($_.Name).old"
+ CategoryInfo : PermissionDenied: (file.dll.old:FileInfo) [Remove-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : RemoveFileSystemItemUnAuthorizedAccess,Microsoft.PowerShell.Commands.RemoveItemCommand
2012-02-16 10:35:31 Processing file2.dll
The trap will only trigger on a terminating error.
rm "$($_.Name).old" -ErrorAction "Stop"