Powershell 错误记录:详细错误


本文索引
[隐藏]

你可以通过Powershell中的自动化变量$Error和Trap 语句块中的$_的内置变量来输出异常的详细信息。在这篇文章来深入了解Error中的记录。在Powershell控制台中一旦错误发生,异常信息会被以红色显示。红色的的设置保存在:

$host.PrivateData.ErrorForegroundColor
# Red
$host.PrivateData.ErrorBackgroundColor
# Black

Powershell控制台输出的错误信息为文本,只包含了部分的错误信息。如果想访问Error的对象信息,可以通过以下的途径:
Redirection:将错误流重定向到一个变量;
ErrorVariable parameter : 将异常保存到一个变量中;
$Error:也会以数组的形式保存出现的所有异常。

重定向错误记录

如果你想把一个命令的执行结果重定向,可以使用重定向操作符”>”

dir "NoSuchDirectory" > Error.txt
Get-Content Error.txt

不幸的是,Error 信息并没有保存到Error.txt 因为Error信息不在标准输出流上,而在Error流上,需要使用”2>”操作符。

Get-Item "NoSuchDirectory" 2> Error.txt
Get-Content .error.txt
Get-Item : 找不到路径“E:NoSuchDirectory”,因为该路径不存在。
所在位置 行:1 字符: 9
+ Get-Item <<<< "NoSuchDirectory" 2> Error.txt
+ CategoryInfo : ObjectNotFound: (E:NoSuchDirectory:String) [Get-Item], ItemNotFound
Exception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand

#将异常重定向到$myerror
$myerror = RemoveItem "NoSuchDirectory" 2>&1
$myError.Exception
找不到路径“E:nosuchthing”,因为该路径不存在。
$myError.InvocationInfo

MyCommand : Remove-Item
BoundParameters : {[Path, System.String[]]}
UnboundArguments : {}
ScriptLineNumber : 1
OffsetInLine : 15
HistoryId : 55
ScriptName :
Line : $myerror = Del "nosuchthing" 2>&1
PositionMessage :
所在位置 行:1 字符: 15
+ $myerror = Del <<<< "nosuchthing" 2>&1
InvocationName : Del
PipelineLength : 1
PipelinePosition : 1
ExpectingInput : False
CommandOrigin : Runspace

#显示清晰的错误标识
$myerror.FullyQualifiedErrorId
PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand

$myError | select CategoryInfo, ErrorDetails,Exception,FullyQualifiedErrorId,InvocationInfo,
PipelineIterationInfo,ScriptStackTrace

CategoryInfo : ObjectNotFound: (E:nosuchthing:String) [Remove-Item], ItemNotFoundExceptio
n
ErrorDetails :
Exception : System.Management.Automation.ItemNotFoundException: 找不到路径“E:nosuchth
ing”,因为该路径不存在。
在 System.Management.Automation.LocationGlobber.ExpandMshGlobPath(String
path, Boolean allowNonexistingPaths, PSDriveInfo drive, ContainerCmdletPro
vider provider, CmdletProviderContext context)
在 System.Management.Automation.LocationGlobber.ResolveDriveQualifiedPat
h(String path, CmdletProviderContext context, Boolean allowNonexistingPaths
, CmdletProvider& providerInstance)
在 System.Management.Automation.LocationGlobber.GetGlobbedMonadPathsFrom
MonadPath(String path, Boolean allowNonexistingPaths, CmdletProviderContext
context, CmdletProvider& providerInstance)
在 System.Management.Automation.PathIntrinsics.GetResolvedPSPathFromPSPa
th(String path, CmdletProviderContext context)
在 Microsoft.PowerShell.Commands.RemoveItemCommand.ProcessRecord()
FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
InvocationInfo : System.Management.Automation.InvocationInfo
PipelineIterationInfo : {0, 1}
ScriptStackTrace :

重定向有时也没必要,因为绝大多数Cmdltes都支持-ErrorVariable 参数。只要你将变量名称传递给-ErrorVariable,Powershell就会自动把出现的错误保存到这个变量中,并且这种保存机制不受ErrorAction配置的影响。

Remove-Item "NoSuchDirectory" -ErrorVariable ErrorStore -ErrorAction "SilentlyContinue"
$ErrorStore
Remove-Item : 找不到路径“E:NoSuchDirectory”,因为该路径不存在。
所在位置 行:1 字符: 12
+ Remove-Item <<<< "NoSuchDirectory" -ErrorVariable ErrorStore -ErrorAction "SilentlyContinue"
+ CategoryInfo : ObjectNotFound: (E:NoSuchDirectory:String) [Remove-Item], ItemNotFo
undException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand

$ErrorStore.GetType().fullName
# System.Collections.ArrayList

$ErrorStore[0].gettype().fullName
#System.Management.Automation.ErrorRecord

$ErrorStore[0].Exception.Message
#找不到路径“E:NoSuchDirectory”,因为该路径不存在。

从上面的例子发现ErrorVariable存储类型为数组,数组元素的类型为:ErrorRecord。另一个问题是,为什么ErrorVariable存储类型为数组?因为有可能碰到下面的情况:

Get-Item "NOSuchDir1","NOSuchDir2","NOSuchDir3" -ErrorAction "SilentlyContinue" -ErrorVariable ErrorStore
$Error.Count
# 3

还有一个小技巧,可以给-ErrorVariable参数前加一个“+”,代表追加存储错误,可以将一连串的错误合并在一个数组,后面可以统一进行分析处理,如下:

Get-Item "NOSuchDir1" -ErrorAction "SilentlyContinue" -ErrorVariable +ErrorStore
Remove-Item "NOSuchDir1" -ErrorAction "SilentlyContinue" -ErrorVariable +ErrorStore
Get-Process "NOSuchDir1" -ErrorAction "SilentlyContinue" -ErrorVariable +ErrorStore
$ErrorStore

Get-Item : 找不到路径“E:NOSuchDir1”,因为该路径不存在。
所在位置 行:1 字符: 9
+ Get-Item <<<< "NOSuchDir1" -ErrorAction "SilentlyContinue" -ErrorVariable +ErrorStore
+ CategoryInfo : ObjectNotFound: (E:NOSuchDir1:String) [Get-Item], ItemNotFoundExcep
tion
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetItemCommand

Remove-Item : 找不到路径“E:NOSuchDir1”,因为该路径不存在。
所在位置 行:1 字符: 12
+ Remove-Item <<<< "NOSuchDir1" -ErrorAction "SilentlyContinue" -ErrorVariable +ErrorStore
+ CategoryInfo : ObjectNotFound: (E:NOSuchDir1:String) [Remove-Item], ItemNotFoundEx
ception
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand

Get-Process : 找不到名为“NOSuchDir1”的进程。请验证该进程名称,然后再次调用 cmdlet。
所在位置 行:1 字符: 12
+ Get-Process <<<< "NOSuchDir1" -ErrorAction "SilentlyContinue" -ErrorVariable +ErrorStore
+ CategoryInfo : ObjectNotFound: (NOSuchDir1:String) [Get-Process], ProcessCommandExc
eption
+ FullyQualifiedErrorId : NoProcessFoundForGivenName,Microsoft.PowerShell.Commands.GetProcessC
ommand

通过$Error查看错误信息

即使你忘记使用ErrorVariable参数去收集异常,Powershell也会自动收集异常,存储在自动化变量$Error中。$Error同样也是数组,每次会把最后发生的异常保存在索引为0的位置,所以查看最后的一个异常可以使用$Error[0]。有没有一种可能,这个数组拼命地存储异常,也会占用内存资源啊。所以可以使用$Error.Clear(),清空异常。即使你不清理异常,这个数组也有最大值的,最大值存储在$MaximumErrorCount自动化变量中,默认为256.

$MaximumErrorCount
# 256
$MaximumErrorCount=267
$MaximumErrorCount
# 267

通过Traps查看错误信息

最后Trap语句中也提供了一种存储错误的方式,自动化变量$_ ,你可以对$_进行深加工,定制你自己的异常信息。

Trap
{
"完蛋了, 貌似出错了: $($_.Exception.Message)";
Continue;
}
Remove-Item "Books" -ea Stop
# 完蛋了, 貌似出错了: 找不到路径“C:UsersMosser LeeBooks”,因为该路径不存在。
本文链接: http://www.pstips.net/powershell-error-record-details.html
请尊重原作者和编辑的辛勤劳动,欢迎转载,并注明出处!

关于 Mooser Lee

我是一个Powershell的爱好者,创建了PowerShell中文博客,热衷于Powershell技术的搜集和分享。本站部分内容来源于互联网,不足之处敬请谅解,并欢迎您批评指正。

发表评论

电子邮件地址不会被公开。 必填项已用*标注