7
votes

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-ChildItem], 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?

3
Give some code that you are usingmanojlds

3 Answers

8
votes

have you used silentlycontinue?

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

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) {
...
}
0
votes

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
}