使用 ECHO 在 Powershell 中运行 CMD 代码

问题描述 投票:0回答:2

如何在 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 batch-file cmd
2个回答
3
投票

您不能直接从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." }

1
投票

编辑以测试每个评论的退出代码:

#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
}
© www.soinside.com 2019 - 2024. All rights reserved.