收集文件权限,导出为CSV,导出“拒绝访问”文件路径

时间:2017-07-19 21:11:08

标签: powershell error-handling

我正在收集有关网络驱动器权限的数据,我已经能够获取我想要的数据,但我希望能够更好地处理错误,尤其是对于“访问被拒绝”,我没有权限查看文件夹权限。

$PathtoScan = "\\folderxxx\folderyyy"

$GetFileInfo=Get-ChildItem "$PathtoScan" -Recurse -ErrorAction Stop | 
Where {$_.Mode -match "d"} | 
Get-NTFSAccess | Select-Object Name,FullName,InheritanceEnabled,IsInherited, 
InheritedFrom, AccessRights, Account |
Export-Csv C:\Scripts\dump.csv -NoTypeInformation

try {

$GetFileInfo

} 
catch [System.UnauthorizedAccessException] {Write-Host "Message: 
[$($_.Exception.Message)" | Out-File C:\Scripts\test.txt ]

}

我试图捕获的错误消息:

Get-NTFSAccess : (5) Access is denied: [\\folderxxx\folderyyy]
At C:\Scripts\ACL.ps1:4 char:1
+ Get-NTFSAccess | Select-Object Name,FullName,InheritanceEnabled,IsInh ...

+ CategoryInfo          : WriteError: (\\folderxxx\folderyyy) [Get-NTFSAccess], UnauthorizedAccessException
+ FullyQualifiedErrorId : ReadSecurityError,NTFSSecurity.GetAccess

理想情况下,我想将路径导出到我无权访问的位置,以查看修复权限。

我使用:$Error[0].exception | Get-Member来更好地了解我想要捕获的错误:System.UnauthorizedAccessException

有什么想法吗?

谢谢!

2 个答案:

答案 0 :(得分:4)

这里有很多错误。

首先,你这样做:

$GetFileInfo = Get-ChildItem [...] |
[...] |
Export-Csv C:\Scripts\dump.csv -NoTypeInformation

Export-Csv根本不会将任何对象返回到标准输出。您可以使用-PassThru参数覆盖执行此操作的某些cmdlet,但Export-Csv不支持该参数。 $GetFileInfo 总是将成为$null。您的脚本结构让我觉得您不了解管道和输出的工作原理。当你写下这样的东西时:

$x = Get-Item -Path C:\

当您致电$x时,您不会编写要执行的命令。命令立即执行 将这些命令的标准输出分配给变量$x

你似乎在后面的catch块中犯了同样的错误:

Write-Host "Message: [$($_.Exception.Message)" | Out-File C:\Scripts\test.txt ]

我不知道这是怎么做的,但我保证它不会做你认为它做的事情。同样,Write-HostOut-File都不会将输出发送到标准输出,并且cmdlet都不支持-PassThru。看:

PS C:\> Write-Host Hello World | Out-File C:\test.txt
Hello World
PS C:\> Get-Content C:\test.txt
PS C:\>

我所做的只是打印“Hello World”并在C:\test.txt创建一个空文件。 Write-Host非常具有欺骗性,因为它看起来像是在写标准输出,但事实并非如此。它直接写入控制台。这就是您经常看到人们说“您可能想要Write-Output而不是Write-Host”的原因,因为Write-Output会写入标准输出。但是,这不是必要的。您通常根本不能使用cmdlet进行输出。

我猜你想要这个:

"Message: [$($_.Exception.Message)]" | Out-File C:\Scripts\test.txt -Append

接下来,您还要这样做来过滤目录:

$GetFileInfo = Get-ChildItem "$PathtoScan" -Recurse -ErrorAction Stop | 
Where {$_.Mode -match "d"} | 

您永远不想使用Mode属性。它非常慢。事实上,ModeGet-ChildItem因默认输出而变慢的原因。如果只需要目录,请执行以下操作:

$GetFileInfo = Get-ChildItem "$PathtoScan" -Recurse -Directory -ErrorAction Stop |
Get-NTFSAccess | [...]

或者,在PowerShell v2及更早版本中:

$GetFileInfo = Get-ChildItem "$PathtoScan" -Recurse -ErrorAction Stop |
Where-Object { $_.PSIsContainer } |
Get-NTFSAccess | [...]

所以,上面让我们更接近:

$PathtoScan = "\\folderxxx\folderyyy"

try {
    Get-ChildItem "$PathtoScan" -Recurse -Directory -ErrorAction Stop | 
    Get-NTFSAccess | Select-Object Name,FullName,InheritanceEnabled,IsInherited, 
    InheritedFrom, AccessRights, Account |
    Export-Csv C:\Scripts\dump.csv -NoTypeInformation
} 
catch {
    "Message: [$($_.Exception.Message)" | Out-File C:\Scripts\test.txt ]
}

但是,在Get-ChildItem引发的第一个错误中,这仍然会完全停止执行。再说一次,这可能不是你想要的。我猜你想要更接近这个:

$PathtoScan = "\\folderxxx\folderyyy"

# Clear the automatic error variable
$Error.Clear()

# Run the commands, but don't stop for any errors encountered and export the results to file
Get-ChildItem "$PathtoScan" -Recurse -Directory -ErrorAction SilentlyContinue | 
Get-NTFSAccess | Select-Object Name,FullName,InheritanceEnabled,IsInherited, 
InheritedFrom, AccessRights, Account |
Export-Csv C:\Scripts\dump.csv -NoTypeInformation

# If there were errors
if ($Error) {
    # Reverse the $Error ArrayList variable to put the oldest events first
    $Error.Reverse()

    # Write all the errors from the automatic error variable to file
    $Error | ForEach-Object {
        "Message: [$($_.Exception.Message)]"
    } | Out-File C:\Scripts\test.txt # You might want an -Append here
}

答案 1 :(得分:1)

您尝试在已经发生错误后尝试捕获错误。在$GetFileInfo块中包含Try{}的初始分配。在您的示例中,我甚至不确定您为什么首先将该命令流分配给变量。如果您尝试取消输出,则应执行$Null=

要确切知道要使用Catch [Errortype]抛出哪个错误,请输入

Catch { Write-Output "[$($_.Exception.GetType().FullName)] $($_.Exception.Message)" }

在您的区块中。我还建议在开头使用$ErrorActionPreference='Stop'