powershell - PowerShell try-catch 丢失重复的访问错误
问题描述
Try-catch似乎不能可靠地捕获所有错误。Try-catch onget-ChildItem
不会报告在 try-catch 之外报告的所有访问错误。
编辑:try-catch 不可靠是不正确的,它只报告一个错误是有充分理由的。请参阅我对已接受答案的评论,以了解我对这个问题的误解。
在运行 PowerShell 5.1 的 Windows 10 Pro 64 中,此脚本:
$sScriptName = "ErrorTest.ps1"
write-host ("I will get the file structure of ""C:\Windows\System32"", but this yields two access-denied errors:")
$aoFileSystem = @(get-ChildItem "C:\Windows\System32" -recurse -force)
write-host ("I will now do it again and trap for those errors. But I only get one of them:")
try {$aoFileSystem = @(get-ChildItem $sPath -recurse -force -ErrorAction Stop)}
catch [System.UnauthorizedAccessException]
{$sErrorMessage = $_.ToString()
write-host ("System.UnauthorizedAccessException: " + $sErrorMessage.substring(20, $sErrorMessage.length - 32))}
以管理员身份在 ISE 中运行,得到以下输出:
PS C:\WINDOWS\system32> D:\<path>\ErrorTest.ps1
I will get the file structure of "C:\Windows\System32", but this yields two access-denied errors:
get-ChildItem : Access to the path 'C:\Windows\System32\config\systemprofile\AppData\Local\Microsoft\Windows\INetCache\Content.IE5' is denied.
At D:\<path>\ErrorTest.ps1:5 char:19
+ ... aoFileSystem = @(get-ChildItem "C:\Windows\System32" -recurse -force)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\Windows\Syst...che\Content.IE5:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
get-ChildItem : Access to the path 'C:\Windows\System32\LogFiles\WMI\RtBackup' is denied.
At D:\<path>\ErrorTest.ps1:5 char:19
+ ... aoFileSystem = @(get-ChildItem "C:\Windows\System32" -recurse -force)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : PermissionDenied: (C:\Windows\Syst...es\WMI\RtBackup:String) [Get-ChildItem], UnauthorizedAccessException
+ FullyQualifiedErrorId : DirUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
I will now do it again and trap for those errors. But I only get one of them:
System.UnauthorizedAccessException: C:\WINDOWS\system32\config\systemprofile\AppData\Local\Microsoft\Windows\INetCache\Content.IE5
PS C:\WINDOWS\system32>
我想记录访问错误,但是当我尝试捕获它们时,我只得到第一个。当我诱捕他们时,我需要做什么才能让第二个出现?
编辑:我收到一条消息,告诉我需要编辑我的问题以解释它与GetChildItem 中的 PowerShell 捕获错误并继续循环有何不同?. 因此,我将在此重复我在回应 Scepticalist 下面的评论时所说的话。这个问题是get-ChildItem
循环的ForEach
。我的问题不涉及这样的循环。尽管如此,我还是从那里接受的答案中尝试了一些东西,使用-ErrorAction SilentlyContinue
,但是隐藏了错误而不捕获它们。但是,在我找到并即将作为答案发布的解决方案中,我确实-ErrorAction SilentlyContinue
与-ErrorVariable
.
解决方案
发出的错误
Get-ChildItem "C:\Windows\System32" -recurse -force
是非终止错误,并且,鉴于根据定义,此类错误不会终止命令,因此单个命令可能会发出多个此类错误。- cmdlet 发出的所有非终止错误都可以在指定变量中捕获,您将其名称传递给
-ErrorVariable
common 参数。 - 此外,默认情况下,所有错误(非终止和终止错误)都记录在会话全局自动
$Error
收集变量中。
- cmdlet 发出的所有非终止错误都可以在指定变量中捕获,您将其名称传递给
try
/catch
仅作用于终止错误,因此默认情况下它对仅发出非终止错误的命令没有影响,例如Get-ChildItem "C:\Windows\System32" -recurse -force
-ErrorAction Stop
您可以通过添加(使用common 参数)指示命令将遇到的第一个非终止错误转换为终止错误-ErrorAction
,在这种情况下,封闭的try
/catch
确实会捕获错误,但请注意,在遇到第一个错误之后执行会停止方式。
警告:有两种类型的终止错误(以及可能存在历史事故的事实);虽然这两种类型都可以用try
/捕获catch
,但它们的默认行为不同:
语句终止错误,仅终止手头的语句,并在发出错误消息后默认继续执行脚本;通常,如果遇到不限于手头输入且不允许它们继续处理进一步输入的错误,则这些错误由(编译的)cmdlet 发出。
脚本终止错误(运行空间终止错误),默认情况下完全中止处理。使用该
Throw
语句的 PowerShell 代码会生成此类错误,就像传递-ErrorAction Stop
给发出非终止错误的命令一样。- 警告:虽然
-ErrorAction Stop
对语句终止错误没有影响,但看似等效的首选项变量设置,意外地将语句终止错误提升为脚本终止错误。$ErrorActionPreference = 'Stop'
- 警告:虽然
进一步阅读:
有关 PowerShell(令人眼花缭乱的复杂)错误处理的全面概述,请参阅此 GitHub 文档问题。
至于在编写命令时何时报告终止错误与非终止错误,请参阅此答案。
推荐阅读
- javascript - 将单个添加到 ajax 添加的 javascript 行
- r - Capture.output 不考虑 r 中的控制台大小
- html - 使用 python urllib3 获得对网络服务器的授权访问时出现问题
- c# - 异步方法的布尔检查
- reactjs - 更改反应输入时保持 e.target
- flutter - (HttpException) => Null' 不是 '(dynamic) => dynamic' 类型的子类型!!扑
- python - Tensorflow,Keras:“模型”对象没有属性“_get_distribution_strategy”
- python - 删除停用词/标点符号,标记并应用 Counter()
- python - 登录hotmail python 3.x
- node.js - 如何在猫鼬中获取最后一条记录的一个值