如何在 PowershellScript 中执行以下示例?
@echo off
REM Maintenance Mode on
"C:\ProgramFiles\vdogServer\VDogMasterService.exe" /at:s /rd:C:\vdServerArchive /maintenance:on
if ERRORLEVEL 1 ECHO "versiondog Server wurde nicht ordnungsgemäß in den Wartungsmodus versetzt." >> d:\log.txt
if ERRORLEVEL 0 ECHO "versiondog Server wurde ordnungsgemäß in den Wartungsmodus versetzt." >> d:\log.txt
我试过了没有成功:
$command = @'
@echo off
REM Maintenance Mode on
"D:\vdogServer\VdogMasterService.exe" /at:s /rd:E\vdServerArchive /maintenace :on
if ERRORLEVEL 1 ECHO "NOK" >> d:\MMLOG.txt
if ERRORLEVEL 0 ECHO "OK" >> d:\MMLOG.txt
'@
Invoke-Expression -Command:$command
我还是 Powershell 的初学者,如果有人对此有解决方案,那就太好了,BR
您不能直接从PowerShell(使用一种非常不同的语言)执行批处理文件(
cmd
)命令,但是
您可以 pipe 一系列批处理文件命令到 cmd
,(遗留)Windows 命令处理器,但它有 严重的局限性:
$commands = @'
@echo off
REM Maintenance Mode on
"D:\vdogServer\VdogMasterService.exe" /at:s /rd:E\vdServerArchive /maintenace :on
if ERRORLEVEL 1 ECHO "NOK" >> d:\MMLOG.txt
if ERRORLEVEL 0 ECHO "OK" >> d:\MMLOG.txt
'@
# !! THIS MAY OR MAY NOT WORK AS INTENDED, DEPENDING ON THE SPECIFIC COMMANDS.
# Simply sends the commands via stdin.
# /q suppresses printing the prompt between commands, and
# /d suppresses autorun entries - see cmd /?
$commands | cmd /q /d
限制:
for
循环并转义 %
字符。不工作,
因为,cmd.exe
解析通过 stdin 提供的命令,期望 interactive 命令行语法,而不是 batch-file 语法,遗憾的是,由于历史原因 - 不同:
%%i
作为迭代器变量,而交互地您必须使用%i
(只是one%
);例如,通过 stdin 提供诸如 for /l %%i in (1,1,3) do echo %%i
的声明是 quiet no-op.%
符号转义为 %%
(将它们用作 文字):例如,您可以使用 %%PATH%%
在输出中生成 文字 %PATH%
;在命令行上 - 以及通过标准输入进行管道传输时 - 这不起作用:你最终得到 %<value of variable>%
。
使用这种调用方式,
cmd
将 not 自动在其自己的退出代码中反映最后一个命令的退出代码,因此 PowerShell 的 $LASTEXITCODE
将不会反映失败。 (将此与调用包含相同命令的 batch file 进行对比。)
exit
调用退出以正确设置退出代码。字符编码警告:您需要(暂时)设置
$OutputEncoding = [Console]::InputEncoding
以确保包含非 ASCII 字符的批处理命令按照 cmd.exe
期望的方式进行编码(即,基于活动OEM 代码页)。
最后,还有一个cosmetic问题,但是,也会影响输出的处理programmatically:
@echo off
作为第一行,cmd.exe
的版权信息总是首先打印(例如,Microsoft Windows [Version 10.0.19044.1826]...
),然后是提示字符串的一个实例(例如C:\>
)出于这些原因,通常最好将命令写入(临时)批处理文件并调用它:
注意:您还可以使用此功能来执行从 web 下载的批处理文件的内容,使用
Invoke-WebRequest
/ Invoke-RestMethod
,如 this related question 中所要求的那样。
function Invoke-AsBatchFile {
param(
[string] $batchFileContents
)
# Determine a unique file path to serve as a temp. batch file.
$tempBatchFile = "$(Join-Path ([IO.Path]::GetTempPath()) ([IO.Path]::GetRandomFileName())).cmd"
# Write the commands to the batch file.
# Note: -Encoding OEM assumes that the current console window's
# active code page is at its default, the system's active OEM code page.
$batchFileContents | Set-Content -Encoding OEM -LiteralPath $tempBatchFile
# Execute the temp. batch file with pass-through arguments, if any.
# (Reflected in the automatic $args variable.)
& $tempBatchFile $args
# Remove the temp. batch file.
Remove-Item $tempBatchFile
# $LASTEXITCODE now contains the temp. batch file's exit code
# (whereas $? should be ignored).
}
调用示例:
$command = @'
@echo off
REM Maintenance Mode on
"D:\vdogServer\VdogMasterService.exe" /at:s /rd:E\vdServerArchive /maintenace :on
if ERRORLEVEL 1 ECHO "NOK" >> d:\MMLOG.txt
if ERRORLEVEL 0 ECHO "OK" >> d:\MMLOG.txt
'@
Invoke-AsBatchFile $command
if ($LASTEXITCODE -ne 0) { Write-Error "Something went wrong." }
编辑以测试每个评论的退出代码:
#Maintenance Mode on
& "C:\ProgramFiles\vdogServer\VDogMasterService.exe" /at:s /rd:C:\vdServerArchive /maintenance:on
if ($LASTEXITCODE -eq 0) {
"versiondog Server wurde ordnungsgemäß in den Wartungsmodus versetzt." | out-file d:\log.txt -append
} else {
"versiondog Server wurde nicht ordnungsgemäß in den Wartungsmodus versetzt." | out-file d:\log.txt -append
}