首页 > 解决方案 > 检查批处理文件是否在PowerShell中成功运行

问题描述

我在 powershell 脚本中运行批处理文件。

Powershell 脚本(pw.ps1):

 # Powershell script

$ScriptPath = "C:\Users\Administrator\Documents\bh.bat"

$out = cmd.exe /c "$ScriptPath" 2>&1 | Out-String

$flg = $?

echo "Output: $out"

if ($flg) {
    echo "Worked"
} else {
    echo "Failed"
}

批处理文件(bh.bat):

REM Batch File

@echo on

Setlocal EnableDelayedExpansion

schtasks /query /tn T1

if %errorlevel% NEQ 1 (
  echo "Task already scheduled"
) else (
  echo "Task not scheduled"
)

exit /b 0

powershell脚本的输出:

 PS C:\Users\Administrator\Documents> C:\Users\Administrator\Documents\pw.ps1
Output: 
C:\Users\Administrator\Documents>REM Batch File 

C:\Users\Administrator\Documents>Setlocal EnableDelayedExpansion 

C:\Users\Administrator\Documents>schtasks /query /tn T1 
cmd.exe : ERROR: The system cannot find the path specified.
At C:\Users\Administrator\Documents\pw.ps1:5 char:8
+ $out = cmd.exe /c "$ScriptPath" 2>&1 | Out-String
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (ERROR: The syst...path specified.:String) [], RemoteException
    + FullyQualifiedErrorId : NativeCommandError


C:\Users\Administrator\Documents>if 1 NEQ 1 (echo "Task already scheduled" )  else (echo "Task not scheduled" ) 
"Task not scheduled"

C:\Users\Administrator\Documents>exit /b 0 

Failed

PS C:\Users\Administrator\Documents> 

我的要求如下:

  1. 只有当批处理脚本因语法或运行时错误等错误而失败时,Powershell 脚本才应输出“Failed”。
  2. Powershell 脚本应在两种情况下输出“Worked”:找到或未找到任务。目前,如果找不到任务,Powershell 脚本会给出“失败”作为输出。

如果批处理文件成功运行,如何签入 powershell 脚本?

标签: windowspowershellbatch-file

解决方案


更改批处理文件如下:

@echo off
setlocal enabledelayedexpansion

schtasks /query /tn T1

:: Analyze the exit code (error level)
:: and map it onto a custom exit code.
:: Note that schtasks doesn't report *specific* error
:: exit codes: 1 means that *something* went wrong,
:: which we assume to be that the task doesn't exist.
if ERRORLEVEL 1 (
  echo Task not scheduled
  set ec=101
) else ( 
  echo Task already scheduled
  set ec=100
)

:: Getting here implies success.
:: Use the custom exit code to report the specific success status.
:: Note: If this batch file is aborted due a syntax error,
::       the caller will see exit code 255. 
exit /b %ec% 

然后从您的 PowerShell 脚本中调用它,如下所示:

# Note: 
#  * No need to call via `cmd /c` in this case - you can invoke batch
#    files directly.
#  * Doing so has the added advantage of PowerShell *itself* reporting
#    a statement-terminating error if the batch file cannot b found,
#    which we handle via a try / catch statement.
try {

  $out = & $ScriptPath 2>&1 | Out-String

  # No need for `echo` (alias for `Write-Output`) - implicit output will do.
  "Output: $out"

  # Check the automatic $LASTEXITCODE variable for the exit code from the
  # most recently executed external program.
  # We infer success if we see one of the two custom exit codes.
  $ok = $LASTEXITCODE -in 100, 101

} catch {
  # This only happens if the batch file doesn't exist.
  $ok = $false
  $LASTEXITCODE = 2 # Simulated exit code: File not found.
}

if ($ok) { # task exists or doesn't exist.
  "Worked"
} else {   # something fundamental went wrong
  "Failed with exit code $LASTEXITCODE"
}

笔记:

  • 虽然批处理文件可能有语法错误- 这会导致其执行被中止并且调用者看到退出代码255- 任何其他错误都通过退出代码(错误级别)报告 - 并且由每个命令/可执行文件正确设置退出代码,按照0惯例指示成功,以及任何非零值失败。并非所有可执行文件都遵守此约定:

    • 有些总是报告0,即使遇到错误情况。
    • 有些人只报告两个退出代码:成功和任何错误-0属于1这一类。schtasks.exe
    • 有些会使用特定的退出代码传达特定的结果,从而允许您检测特定的(错误条件)。
    • 一些,值得注意的是robocopy.exe,甚至使用(必要的)非零退出代码来传达特定的成功状态——这种技术也用在上面的代码中。
  • 如果您只需要知道批处理文件是否由于语法错误而异常退出,您可以不用自定义退出代码而只需使用
    $ok = $LASTEXITCODE -ne 255

  • 由于您的批处理文件使用明确设置了特定的退出代码,因此exit /b <n>从 PowerShell 直接调用(使用调用运算符)可以正常工作,但请注意- 请注意- 通常是调用批处理文件的最可靠方法- 请参阅此答案&
    cmd.exe /c call <batch-file>call


推荐阅读