windows - 检查批处理文件是否在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>
我的要求如下:
- 只有当批处理脚本因语法或运行时错误等错误而失败时,Powershell 脚本才应输出“Failed”。
- Powershell 脚本应在两种情况下输出“Worked”:找到或未找到任务。目前,如果找不到任务,Powershell 脚本会给出“失败”作为输出。
如果批处理文件成功运行,如何签入 powershell 脚本?
解决方案
更改批处理文件如下:
@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
推荐阅读
- java - 在类路径中的spring boot中访问文件夹
- python - 在 discord.py 上引发异常(类型错误)的错误处理程序
- r - 向多个地图添加图例
- reactjs - 在 WebStorm 中,如何在 React 中禁用道具缩进?
- r - 如何从字符串列中提取数字并确定它们是否小于阈值?
- arrays - C程序中的下标值既不是数组也不是指针也不是向量
- google-apps-script - 清除 g-sheet 内容永远不会完成
- javascript - 当父 THREE.js 组的可见性改变时改变 CSS2D 对象的可见性
- javascript - 如何获取选中复选框的列表?
- wordpress - 标志没有变化