当我的PowerShell脚本试图为不存在的服务器(在我的情况下是“bla”)创建SQL Server对象时,PowerShell会显示许多红色的PowerShell错误。
由于我的脚本在此类调用之后检查$?
的值,并显示和记录错误,因此我不想再显示几行PowerShell错误。
我应该如何禁止这些错误显示在我的脚本中?
当我的PowerShell脚本试图为不存在的服务器(在我的情况下是“bla”)创建SQL Server对象时,PowerShell会显示许多红色的PowerShell错误。
由于我的脚本在此类调用之后检查$?
的值,并显示和记录错误,因此我不想再显示几行PowerShell错误。
我应该如何禁止这些错误显示在我的脚本中?
您有几个选择。 最简单的方法涉及使用ErrorAction
设置。
-Erroraction
是所有cmdlets的通用参数。 如果有特殊命令要忽略,可以使用-erroraction 'silentlycontinue'
,这将基本上忽略该命令生成的所有错误消息。 您还可以使用Ignore
值(在PowerShell 3+中):
与SilentlyContinue不同,Ignore不会将错误消息添加到$Error自动变量中。
如果要忽略脚本中的所有错误,则可以使用系统变量$ErrorActionPreference
并执行相同操作:$ErrorActionPreference= 'silentlycontinue'
有关-ErrorAction的更多信息,请参见about_CommonParameters。 有关$ErrorActionPreference的更多信息,请参见about_preference_variables。
您还可以在命令后附加2>$null
。
例如:
$rec = Resolve-DnsName $fqdn -Server $dns 2>$null
Windows PowerShell提供了两种报告错误的机制:一种用于终止错误,另一种用于非终止错误。
内部CmdLets代码可能会在发生错误时调用ThrowTerminatingError
方法,这些错误可能不允许命令继续处理其输入对象。脚本编写者可以使用异常来捕获这些错误。
例如:
try
{
Your database code
}
catch
{
Error reporting/logging
}
在处理输入对象时,内部 CmdLets 代码可以调用 WriteError
方法报告非终止错误。脚本编写者可以使用 -ErrorAction 选项隐藏这些消息,或使用 $ErrorActionPreference
设置整个脚本的行为。
在您的脚本中添加 -ErrorAction SilentlyContinue
,就可以顺利运行了。
你的想法偏离了正确的方向。几乎从来不建议消除错误,并在每个命令之后显式地手动检查$?
是非常麻烦和容易被遗忘(易出错)的。不要让自己轻易犯错。如果你得到大量红色错误,这意味着你的脚本应该停止运行,而不是继续执行。如果大多数命令都失败了,它就不能再执行有用的工作了。当程序和系统处于未知状态时,继续运行程序将产生未知的后果;你很容易会让系统处于一种损坏状态。
正确的解决方案是在第一个错误发生时停止程序。这个原则被称为“快速失败”,PowerShell 有一种内置机制来启用这种行为。它是一个叫做“error preference”的设置,将它设置为最高级别将使你的脚本(以及子范围,如果它们没有覆盖该设置)表现出这种行为:
$ErrorActionPreference = 'Stop'
$?
。这使得代码更加简单可靠。我会把它放在我写的每一个脚本的顶部,你也应该这样做。catch
: 这是更好、更灵活的机制。您可以在多个命令周围包装一个try
/catch
块,允许第一个错误停止序列并跳转到处理程序,在那里您可以记录它,然后以其他方式从中恢复或重新抛出它以进一步传递错误。您还可以限制catch
只针对特定错误,这意味着它只会在您预期的特定情况下被调用,而不是任何错误。(例如,因为文件已经存在而无法创建文件会引起与安全故障不同的响应。)
- 常见的-ErrorAction
参数: 此参数更改一个函数调用的错误处理,但您无法将其限制为特定类型的错误。只有当您可以确定脚本可以在任何错误下继续运行时,才应使用此选项。try
/catch
块。然后,在第一个错误处停止进程,catch
块可以记录它并退出。这将从您的程序中删除许多重复代码,除了清理日志文件和终端输出外,还会使您的程序更不容易引起问题。$LASTEXITCODE
。尽管存在这种限制,但该设置仍然节省了大量的代码和精力。Set-StrictMode -Version Latest
这可以防止PowerShell在使用不存在的变量和其他奇怪情况下默默地执行。(有关其限制的详细信息,请参见-Version
参数。)
将这两个设置结合起来使PowerShell更容易出错,这使得在其中进行编程大大简化。
我曾经在使用 [system.net.dns]
解析主机名时遇到了类似的问题。如果无法解析IP地址,.Net会抛出一个终止错误。
为了防止终止错误并仍然保留输出的控制权,我创建了一个使用 TRAP
的函数。
例如:
Function Get-IP
{PARAM ([string]$HostName="")
PROCESS {TRAP
{"" ;continue}
[system.net.dns]::gethostaddresses($HostName)
}
}
扩展Mikkel的答案.
如果您仍然想捕获错误,可以使用“-ErrorAction stop”结合try-catch。
“-ErrorAction silentlycontinue”将忽略错误。
例如:
try
{
New-Item -Path "/somepath" -Name "somename" -ErrorAction Stop | Out-Null
}
catch
{
echo "You must run this command in an elevated mode."
}
注意:并没有“silentlyStop”动作,我认为Mickel的回答指的是“stop”动作。这很可能是一个打字错误。 使用try-catch与“stop”动作结合的想法是为了能够不仅可以忽略潜在的错误,而且在发生错误时显示一些内容。
command | Out-Null
如果您想抑制 cmdlet 的 PowerShell 错误消息,但仍然想捕获错误,请使用“-erroraction 'silentlyStop'”
New-Item -ItemType directory
(PowerShell v2.0)时仍然使用catch命令/部分 - Milan Kerslager
-ErrorAction:SilentlyContinue
。因为我是从批处理中调用我的cmdlet,所以我不知道这是否有所不同。但是当您知道可能会抛出可接受的错误时,这是一个好消息。 - David