使用ECHO在Powershell中运行CMD代码

时间:2016-10-05 14:33:28

标签: powershell batch-file cmd

如何在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

2 个答案:

答案 0 :(得分: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
}

答案 1 :(得分:1)

你不能直接执行PowerShell中的批处理文件(cmd)命令(这是一种非常不同的语言),但是 您可以管道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
'@

# Simply sends the commands via stdin.
#  /q suppresses printing the prompt between commands, and
#  /d suppresses autorun entries - see cmd /?
$commands | cmd /q /d

但它附带警告

  • 使用此调用样式,cmd在其自己的退出代码中反映最后一个命令的退出代码,因此PowerShell的 $LASTEXITCODE将不会反映失败。 (与此相反,调用包含相同命令的批处理文件。)

  • 默认使用PowerShell 使用ASCII作为输出编码($OutputEncoding);即,仅向外部命令发送ASCII字符 ,只需用文字? 替换非ASCII字符。

    • 你可以(暂时)设置$OutputEncoding = [text.encoding]::Default来解决这个问题,它解决了事物的输入方面并重定向到输出文件,但请注意 console 输出是一个单独的问题,并且会仍然歪曲非ASCII字符(您必须(暂时)设置[Console]::OutputEncoding
  • 在一个更微妙但可能更隐蔽的注释中,命令使用交互式命令行语法解析,而不是批处理文件语法,令人遗憾的是,由于历史原因,它们略有不同。

    • 这主要涉及转义%符号(将它们用作文字):例如,在批处理文件中,您可以使用%%PATH%%来生成输出上的文字 %PATH%(即,加倍元字符%会导致字面处理);在命令行上 - 当通过标准输入管道 - 这不起作用:你最终得到%<contents of variable %PATH%>%
    • 关于整个可怕的故事,请参阅我的this answer

因此,通常最好将命令写入(临时)批处理文件并调用

function Invoke-AsBatchFile([string] $batchFileContents, $ArgumentList) {
  # 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: Not specifying an -Encoding value means that the Default Windows code page 
  # (e.g., Windows 1252 on a en-US system) is used as the output file's encoding.
  # Note that echoing string literals contained in $batchFileContents to files using
  # `>` (output redirection) therefore also creates output files that are encoded that way. 
  $batchFileContents | Set-Content -LiteralPath $tempBatchFile
  # Execute the temp. batch file with optional arguments.
  # Note that output sent to the *console* is by default still interpreted as 
  # *OEM* codepage-encoded; to change that, also (temporarily) set 
  #   [Console]::OutputEncoding = [text.encoding]::Default
  & $tempBatchFile $ArgumentList
  # 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." }