Powershell: 我如何阻止错误显示在脚本中?

例如,当我的 PowerShell 脚本尝试为不存在的服务器创建 SQL Server 对象时(在我的例子中是“ bla”) ,PowerShell 会以红色显示大量 PowerShell 错误。

由于我的脚本在这样的调用之后检查 $?的值,并显示和记录错误,所以我宁愿不显示 PowerShell 错误的几行。

我怎样才能停用那些为我的脚本显示?

330352 次浏览

您有一对夫妇的选择。最简单的涉及使用 ErrorAction设置。

-Erroraction是所有 cmdlet 的通用参数。如果有一些特殊的命令需要忽略,那么可以使用 -erroraction 'silentlycontinue',它基本上会忽略该命令生成的所有错误消息。您还可以使用 Ignore值(在 PowerShell 3 + 中) :

Unlike SilentlyContinue, Ignore does not add the error message to the $Error automatic variable.

如果希望忽略脚本中的所有错误,可以使用系统变量 $ErrorActionPreference并执行相同的操作: $ErrorActionPreference= 'silentlycontinue'

有关 -ErrorAction 的更多信息,请参见 About _ CommonParameter。 有关 $ErrorActionPreferences 的更多信息,请参见 About _ 偏好 _ 变量

Windows PowerShell 提供两种报告错误的机制: 一种是 终止错误的机制,另一种是 非终止性错误非终止性错误的机制。

当发生不允许或不应该允许 cmdlet 继续处理其输入对象的错误时,内部 CmdLets 代码可以调用 ThrowTerminatingError方法。脚本编写器可以使用异常来捕获这些错误。

例如:

try
{
Your database code
}
catch
{
Error reporting/logging
}

Internal CmdLets code can call a WriteError method to report non-terminating errors when the cmdlet can continue processing the input objects. The script writer can then use -ErrorAction option to hide the messages, or use the $ErrorActionPreference to setup the entire script behaviour.

我在尝试使用 [system.net.dns]解析主机名时遇到了类似的问题。如果 IP 地址没有解决的话。Net 抛出了一个终止错误。 为了防止终止错误并保持对输出的控制,我使用 TRAP创建了一个函数。

脑电图。

Function Get-IP
{PARAM   ([string]$HostName="")
PROCESS {TRAP
{"" ;continue}
[system.net.dns]::gethostaddresses($HostName)
}
}

如果希望禁用 cmdlet 的 powershell 错误消息,但仍然希望捕获错误,请使用“-erroraction‘ silentlyStop’”

你说的太离谱了。消除错误几乎从来都不是一个好主意,而且在 每一个命令之后显式地手动检查 $?非常麻烦,而且很容易忘记(容易出错)。不要让自己容易犯错误。如果你得到了很多很多的红色,这意味着你的脚本在应该停止的时候继续运行。如果它的大部分命令都失败了,它就不能再做有用的工作了。当程序和系统处于未知状态时继续执行程序将产生未知的后果; 您可能很容易使系统处于损坏状态。

正确的解决办法是停止算法的第一个错误。这个原则被称为“快速失败”,PowerShell 有一个内置的机制来支持这种行为。它是一个称为 错误首选项的设置,将其设置为最高级别将使您的脚本(以及子作用域,如果它们不覆盖它)以这种方式工作:

$ErrorActionPreference = 'Stop'

这将为您的使用生成一个漂亮的大错误消息,并防止在第一次出现错误时执行以下命令,而不必每次运行命令时都检查 $?。这使得代码更加简单和可靠。我把它放在我写的每一个脚本的最上面,你也应该这样做。

In the rare cases where you can be absolutely certain that allowing the script to continue makes sense, you can use one of two mechanisms:

  • catch : 这是更好更灵活的机制。您可以将一个 try/catch块包装在多个命令周围,允许第一个错误停止序列并跳转到处理程序中,在那里您可以记录它,然后从它恢复或者重新抛出它,使错误进一步冒泡。您还可以将 catch限制为特定的错误,这意味着它只会在您预期的特定情况下调用,而不会调用任何错误。(例如,由于文件已经存在而未能创建该文件,因此需要作出与安全性故障不同的响应。)
  • The common -ErrorAction parameter: This parameter changes the error handling for one single function call, but you cannot limit it to specific types of errors. You should only use this if you can be certain that the script can continue on 任何 error, not just the ones you can anticipate.

在您的例子中,您可能需要在整个程序周围放置一个大的 try/catch块。然后您的进程将在第一个错误时停止,并且 catch块可以在退出之前记录该错误。除了清理日志文件和终端输出以及减少程序引起问题的可能性之外,这将从程序中删除大量重复的代码。

请注意,这不能处理外部可执行文件失败的情况(通常,退出代码是非零的) ,因此如果调用任何可执行文件,仍然需要检查 $LASTEXITCODE。尽管有这个限制,设置仍然节省了大量的代码和工作。

额外的可靠性

您可能还需要考虑使用 strict mode:

Set-StrictMode -Version Latest

这可以防止 PowerShell 在使用不存在的变量时以及在其他奇怪的情况下无声地继续运行。(请参阅 -Version参数以了解其限制内容的详细信息。)

将这两种设置结合起来,使得 PowerShell 更像是一种容易失败的语言,这使得用它编程变得非常容易。

-ErrorAction SilentlyContinue添加到您的脚本中,您就可以开始了。

在某些情况下,您可以在命令之后管道输入一个 Out-Null

command | Out-Null

还可以将 2>$null附加到命令。

例如:

$rec = Resolve-DnsName $fqdn -Server $dns 2>$null

对米克尔的回答进行延伸。

如果仍然希望捕获错误,可以使用“-ErrorAction stop”结合 try-catch。

“-ErrorAction SilentlyContine”将忽略该错误。

例如:

try
{
New-Item -Path "/somepath" -Name "somename" -ErrorAction Stop | Out-Null
}
catch
{
echo "You must run this command in an elevated mode."
}


注意: 没有“无声的停止”动作,我相信 Mickel 的答案指的是“停止”动作。可能是打印错误。 使用 try-catch 结合“ stop”操作的想法不仅可以忽略最终的错误,还可以在发生错误时显示一些内容。