使用 Get-Acl 时获取导致 UnauthorizedAccessException 的文件或目录的路径

Get path of file or directory that caused UnauthorizedAccessException when using Get-Acl

我正在使用 Powershell 命令 $TargetFiles = Get-Childitem $TargetPath -Recurse -ErrorAction Stop | Get-Acl

如果此命令由于用户 运行 对某些文件或目录没有足够的权限而失败,则会引发以下错误:

Get-Acl : Attempted to perform an unauthorized operation.
At B:\PS\Script.ps1:20 char:50
+     $TargetFiles = Get-Childitem $TargetPath -Recurse -ErrorAction Stop <<<<
    + CategoryInfo          : NotSpecified: (:) [Get-Acl], UnauthorizedAccessException
    + FullyQualifiedErrorId : System.UnauthorizedAccessException,Microsoft.PowerShell.Commands.GetAclCommand

在处理这个异常时,我想打印出导致权限错误的文件或目录的路径。

如何获取导致此错误的文件或目录的路径?

我曾尝试使用 Get-PSCallStack 等命令并查看 $StackTrace 等变量,但无法从中找到此信息。

我使用的 Powershell 版本:

Major  Minor  Build  Revision
-----  -----  -----  --------
2      0      -1     -1

OS 是 Windows 7.

您可以使用$Error 自动变量查看发生异常的进程。像这样:

$TargetFiles = Get-Childitem $TargetPath -Recurse -ErrorAction Stop

$Error[0]
$Error[0].ErrorRecord.CategoryInfo
$Error[0].ErrorRecord.CategoryInfo.TargetName

不幸的是,似乎 Get-Acl 是抛出异常的代码,虽然它与我们看到的 Get-ChildItem 返回的异常类型相同,但消息不同(Attempted to perform an unauthorized operation 而不是 Access to the path 'c:\whatever' is denied),并且它不会在其数据中携带有问题的路径。

修复是这样的:

try {
    $TargetFiles = $TargetPath | Get-Childitem -Recurse -ErrorAction Stop | ForEach-Object{$_ | Get-Acl -ErrorAction Stop}
} catch [System.UnauthorizedAccessException] {
    $pathWithProblem = $_.TargetObject
    #do what you like with it after this
    $descriptionOfProblem = $_.Exception.Message
    Write-Warning "$descriptionOfProblem : $pathWithProblem"
    throw
}

这看起来有点傻;因为我们只是将对 Get-ACL 的调用包装在 foreach 块中;无论如何,其逻辑由管道输入处理。我很确定这种异常行为是由 PS 生成异常信息的逻辑中的错误引起的,但是这个包装器似乎确实可以解决您的问题。