开发者

Can PowerShell trap errors in GetChildItem and continue looping?

I have a PowerShell script that is recursing down thru the file system using GetChildItem in a for-loop. As it travels, it is fixing ACL issues it finds (mostly where someone has blocked the BUILTIN\Administrators account)... but there are some it can't handle on it's own, like when I get [System.UnauthorizedAccessException] if there is an explicit "Deny" ACE.

The line of code looks like this:

foreach($file in Get-ChildItem $dirRoot -Recurse -ErrorAction Continue) {
    ...
}

When it stumbles on a path it can't read, it gives this exception:

Get-ChildItem : Access to the path 'C:\TEMP\denied' is denied. At Fix-ACLs.ps1:52 char:31 + foreach($file in Get-ChildItem <<<< $dirRoot -Recurse -ErrorAction Continue) { + CategoryInfo : PermissionDenied: (C:\TEMP\denied:String) [Get-ChildI开发者_Python百科tem], Unauthorized AccessException + FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand

I would like to try/catch or trap the error so that I can repair the ACL (that is, remove the "Deny") in-place, and--most importantly--continue the loop without losing my place. Any suggestions for me?


have you used silentlycontinue?

foreach($file in Get-ChildItem $dirRoot -Recurse -ErrorAction silentlycontinue) {
    ...
}


How about Inquire?

foreach($file in Get-ChildItem $dirRoot -Recurse -ErrorAction Inquire) {
...
}

Maybe open up a second PS window to troubleshoot the error then continue the command in the first PS window by selecting Y for continue.

You can also use ErrorVariable

foreach($file in Get-ChildItem $dirRoot -Recurse -ErrorVariable a) {
...
}

Get-Variable a or $a will show you all the errors incurred by the command. You can also use +variablename (+a) to add errors to an existing variable.

foreach($file in Get-ChildItem $dirRoot -Recurse -ErrorVariable +a) {
...
}


Try and Catch blocks will only handle terminating errors so if (as it is in this case) the error is non terminating you will need to define an error action that terminates. If you change your error action to 'Stop' it will jump to the Catch block(s) and then carry on with your script.

You can then create a specific catch block for that error and then attempt to remediate your issue / test.

More info below: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_try_catch_finally?view=powershell-7.2

With that in mind you could do something like the below:

foreach($file in Get-ChildItem $dirRoot -Recurse -ErrorAction Stop) {
        ...
    }
    Catch [System.UnauthorizedAccessException]{
    #Catch error in question, remediate, log or 'PAUSE' for manual intervention
    }
    Catch{
    #Deal with any other errors
    }

Hopefully that is useful.


I would use this to:

ForEach($file in Get-ChildItem $dirRoot -Recurse -ErrorAction silentlycontinue) {
    ...
}

And then, you can filter $Error to get specifically Permission Denied type errors:

$permError += $Error | Where-Object { $_.CategoryInfo.Category -eq 'PermissionDenied' }

ForEach($deniedAccess in $permError)
{
    $deniedAccess.CategoryInfo.TargetName | Do Stuff
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜