Powershell忽略错误

时间:2017-11-21 01:34:06

标签: powershell

如何让powershell忽略遗留命令的失败?

所有powershell模块都支持-ErrorAction,但这不适用于NET STOP等传统命令

NET STOP WUAUSERV
echo $?
true

我想尝试停止服务,如果服务已经停止,请继续。重现这一点的简单方法是尝试两次停止服务。

我尝试过的事情

$ErrorActionPreference = "SilentlyContinue"
NET STOP WUAUSERV
NET STOP WUAUSERV
echo $LASTEXITCODE

尝试使用AND和OR操作符

NET STOP WUAUSERV || $true
NET STOP WUAUSERV || $true
echo $LASTEXITCODE

NET STOP WUAUSERV && $true
NET STOP WUAUSERV && $true
echo $LASTEXITCODE

我也尝试过重定向错误

NET STOP WUAUSERV 2>nul
NET STOP WUAUSERV 2>nul
echo $LASTEXITCODE

根据similar question的建议,我也尝试了

cmd.exe /C "NET STOP WUAUSERV"

如何使这个遗留命令具有幂等性?

3 个答案:

答案 0 :(得分:2)

对于许多常见任务,正确的答案是使用已存在的本机PowerShell命令。

对于此特定示例,正确的路径是使用Stop-Service cmdlet,它将优雅地处理您的条件。

如果您必须使用旧版工具,请参阅此StackOverflow答案:Powershell: Capture program stdout and stderr to separate variables

.exe没有在PowerShell输出管道上放置传统值供您评估,因此尝试比较$true没有任何用处。另见:Windows PowerShell Rethinking the Pipeline

此外,$ErrorActionPreference对旧版.EXE无效。 (而-ErrorAction特定于PowerShell命令。)

答案 1 :(得分:2)

  • 要在PowerShell中静默错误/ stderr输出,请使用2> $null ,而不是2> NUL

    • $ErrorActionPreference 的值不应对调用外部实用程序(控制台应用程序)(例如net.exe,但是 - {{ 3)}从Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.9开始 - 如果值为'Stop'2> $null(实际上,任何流重定向2,错误流)当前触发PowerShell错误。
  • 不幸的是,自Windows PowerShell v5.1 / PowerShell Core v6.0.0-beta.9起,PowerShell 不支持控制操作符&&||。 ;但是,即使它们在这里你也不需要它们(你不会在$true$false中使用它们。

无论stderr输出是否被静音:

  • $LASTEXITCODE包含最近执行的外部实用程序的退出代码。

  • 执行外部实用程序后,如果$?$True,则$LASTEXITCODE0,否则为$False

    < / LI>

关于PowerShell的错误处理的全面讨论 - 关于PowerShell本机命令和外部实用程序 - give your thumbs up here

答案 2 :(得分:0)

My other answer讨论了一般从外部可执行文件处理stderr输出/退出代码。

至于幂等方式停止服务(确保服务处于停止状态):

  • Matthew Wetmore's helpful answer建议使用PowerShell的Stop-Service cmdlet,其中 应该是幂等的:它会停止服务,如果它正在运行,或者是一个no-op if它已经处于停止状态。

    • 停止是同步,除非您使用-NoWait开关(PSv5 +),如我this answer所示。
  • 如果您suggest here Stop-Service确实存在问题(我不知道任何问题),您可以补充使用net.exe Get-Service cmdlet确保服务停止,同时仍检测错误情况:

$svc = 'wuauserv'
if ((Get-Service $svc).Status -ne 'Stopped') {
  net stop $svc
  if ($LASTEXITCODE) { Throw "Failed to stop service $svc."}
} else {
  Write-Verbose -Verbose "(Service $svc is already stopped.)"
}