【问题标题】:How to get command prompt's output into a variable with PowerShell如何使用 PowerShell 将命令提示符的输出转换为变量
【发布时间】:2013-02-08 17:36:03
【问题描述】:

我正在使用 PowerShell v3.0 启动一个新的 cmd.exe 进程,然后我在其中加载 Visual Studio 命令提示符以执行构建,如下所示:

Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuildInVsCommandPrompt -WindowStyle $windowStyle -Wait

这可行,它会打开一个新的命令提示符窗口,我可以看到构建发生,然后在构建完成后命令提示符窗口关闭。我希望能够获取写入命令提示符窗口的文本并将其存储在变量中,以检查构建是否通过。我尝试使用它,但它不起作用; $buildOutput 变量为空:

Start-Process cmd.exe -ArgumentList $cmdArgumentsToRunMsBuildInVsCommandPrompt -WindowStyle $windowStyle -Wait -OutVariable buildOutput
Write-Host "Build output = $buildOutput"

这是有道理的,因为 cmd.exe 进程没有返回任何文本;它只是将它写入它自己的窗口。有没有办法让我能够将该文本存储在一个变量中以供原始 powershell 脚本使用?我知道我可以向 MsBuild 提供一个参数,让它将构建日志写入文件,但我正在寻找一种不涉及写入日志文件并且以后不必删除它的解决方案。

感谢任何建议。谢谢!

感谢到目前为止的所有回复!一个流行的建议是直接调用 MsBuild.exe 而不使用 cmd.exe。我需要通过 cmd.exe 的原因是,如果直接从 MsBuild.exe 调用某些项目(例如 XNA 项目),则无法成功构建。相反,我需要从 Visual Studio 命令提示符调用 MsBuild.exe,以便(我假设)设置所有必需的环境变量。我想我可以直接调用 VS 命令提示符,但它也会有与调用 cmd.exe 相同的问题。如果我找不到 VS 命令提示符,我会回退到直接调用 MsBuild.exe,所以仍然感谢这些答案。

【问题讨论】:

  • 为什么不让它写入日志?您可以使用 PowerShell 立即使用日志文件并为您删除它。
  • 直接调用msbuild(或适当的可执行文件)并避免cmd.exe?我不确定cmd.exe 是否“有”标准输出。也许这受/c 标志的影响?
  • 您可以将其作为后台作业运行(使用 cmd /c)并使用接收作业控制输出的显示和最终处理。
  • 我认为 pst 就在这里。我们直接从 powershell 使用 msbuild。工作一种享受。保持简单...

标签: powershell command-prompt powershell-3.0


【解决方案1】:

编辑:我最终使用了@David Brabant 的答案

我遇到了这个问题并创建了一个回显函数

function echo()
{
    $input
}

让我这样做

$output = &"cmd.exe" $args | echo

【讨论】:

    【解决方案2】:

    我已经使用我的问题的第一条评论中的建议解决了我的问题,即将构建输出写入日志文件,使用它,然后删除它。如果他们需要,这允许我仍然向用户显示带有构建进度的 cmd 窗口,并在构建完成后检查构建输出。它还允许我在另一个进程中运行构建,因此如果我们不希望我们的脚本在继续执行之前等待构建完成,我们可以使用 PassThru。

    我创建了一个 Invoke-MsBuild powershell 模块,以使使用 MsBuild 构建变得轻而易举,同时为附加功能提供了许多参数(构建成功或失败时返回,可以显示/隐藏构建窗口,可以等待/不等待构建完成后,可以自动显示失败构建的构建日志等)。你可以view and download the script from my blog

    【讨论】:

      【解决方案3】:
      $process = New-Object System.Diagnostics.Process;
      $process.StartInfo.UseShellExecute = $false;
      $process.StartInfo.RedirectStandardOutput = $true;
      $process.StartInfo.FileName = "cmd.exe";
      $process.StartInfo.Arguments = $cmdArgumentsToRunMsBuildInVsCommandPrompt;
      $process.Start();
      $outputStream = $process.StandardOutput;
      $outputStream.ReadToEnd();
      

      您也可以重定向StandardError

      【讨论】:

      • 我确信这会起作用(我还没有测试过),但它也会阻止文本被写入 cmd 窗口。理想情况下,我仍然希望将其写入 cmd 窗口,以便用户可以看到构建的进度,然后当构建完成时,我想检查该输出以查看构建是否失败。为有用的答案投票:)
      【解决方案4】:

      您始终可以通过这种方式捕获控制台程序的输出:

      $output = [string](nuget.exe)
      

      这里我使用了 nuget($output 将包含可用的命令列表),但您当然可以使用带有适当参数的 msbuild.exe。

      【讨论】:

      • 如果我想在当前进程上运行构建,这是一个很好的解决方案,但我希望在新进程上运行它,以便它在自己的窗口中弹出,用户可以使用 PassThru如果他们愿意,这样他们就不必在脚本继续执行之前等待构建完成。为有用的答案投票:)
      • 这正是我想要的。仅基于问题的标题,这可以 100% 回答问题。可以理解的是,问题的内容改变了要求。感谢您发布此答案。
      猜你喜欢
      • 1970-01-01
      • 2021-02-28
      • 1970-01-01
      • 1970-01-01
      • 2021-10-04
      • 1970-01-01
      • 1970-01-01
      • 2023-03-09
      • 1970-01-01
      相关资源
      最近更新 更多