【问题标题】:How to tell PowerShell to wait for each command to end before starting the next?如何告诉 PowerShell 在开始下一个命令之前等待每个命令结束?
【发布时间】:2010-12-17 00:33:27
【问题描述】:

我有一个 PowerShell 1.0 脚本来打开一堆应用程序。第一个是虚拟机,其他是开发应用程序。我希望虚拟机在其余应用程序打开之前完成启动。

在 bash 中我只能说 "cmd1 && cmd2"

这就是我所拥有的......

C:\Applications\VirtualBox\vboxmanage startvm superdooper
    &"C:\Applications\NetBeans 6.5\bin\netbeans.exe"

【问题讨论】:

    标签: powershell wait execution


    【解决方案1】:

    通常,对于内部命令,PowerShell 会在开始下一个命令之前等待。此规则的一个例外是基于外部 Windows 子系统的 EXE。第一个技巧是像这样流水线到Out-Null

    Notepad.exe | Out-Null
    

    PowerShell 将等到 Notepad.exe 进程退出后再继续。从阅读代码中可以看出这很漂亮,但有点微妙。您还可以将Start-Process-Wait 参数一起使用:

    Start-Process <path to exe> -NoNewWindow -Wait
    

    如果您使用的是 PowerShell 社区扩展版本,则为:

    $proc = Start-Process <path to exe> -NoNewWindow -PassThru
    $proc.WaitForExit()
    

    PowerShell 2.0 中的另一个选项是使用background job

    $job = Start-Job { invoke command here }
    Wait-Job $job
    Receive-Job $job
    

    【讨论】:

    • 我的错。 Start-Process -Wait 效果很好,但现在我发现这不是我想要的......我实际上正在寻求等到 vm 完成启动。我想这将是艰难的。我想我必须为此找到一个新线程。谢谢,但是。
    • 太棒了,| out-null 正是我所需要的。尝试使用Start-Job,但因为我将函数的结果作为参数传递,它对我有点小气,所以我不能使用最后一个建议......
    • 附带说明,如果您需要使用-ArgumentList 传递多个参数,请使用逗号分隔它们,例如-ArgumentList /D=test,/S
    • 感谢您提供简单的“ | Out-Null”解决方案! “Start-Process -NoNewWindow -Wait”方法的问题在于 PowerShell 会暂停,直到父进程产生的所有子进程都完成,即使父进程在它们之前终止。这导致了我们的安装程序问题。
    • 这是我用来等待 VM 启动 Start-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VmName while((Get-AzureRmVM -ResourceGroupName $ResourceGroupName -Name $VmName -Status | ` select -ExpandProperty Statuses | ` ?{ $_.Code -match "PowerState" } | ` select -ExpandProperty DisplayStatus) -ne "VM running") { Start-Sleep -s 2 } Start-Sleep -s 5 ##给VM是时候来了,这样它就可以接受远程请求了
    【解决方案2】:

    除了使用Start-Process -Wait,通过管道输出可执行文件将使Powershell 等待。根据需要,我通常会通过管道发送到Out-NullOut-DefaultOut-StringOut-String -StreamHere 是一长串其他输出选项。

    # Saving output as a string to a variable.
    $output = ping.exe example.com | Out-String
    
    # Filtering the output.
    ping stackoverflow.com | where { $_ -match '^reply' }
    
    # Using Start-Process affords the most control.
    Start-Process -Wait SomeExecutable.com
    

    我确实想念您引用的 CMD/Bash 样式运算符(&、&&、||)。它 看来我们必须是more verbose with Powershell

    【讨论】:

    • 如果您需要解析输出,这是一个非常好的解决方案!
    • 指出 Out-xxxx 重定向器列表很快让我明白为什么我应该使用 Out-Default 而不是 Out-Null,因为我需要保留控制台输出。
    • 请注意,no 需要额外的工作来同步执行 console 应用程序 - 就像在任何 shell 中一样,这是默认行为。管道到Out-String 将输出更改为单行字符串,而PowerShell默认返回行数组Start-Process 应避免用于控制台应用程序(除非您真的想在 新窗口 中运行它们),因为您将无法捕获或重定向它们的输出。
    • 其实,原生命令是同步运行(带输出)还是异步运行取决于可执行文件。例如,在不捕获输出的情况下,以下仅输出“bingo”。 & 'C:\Program Files\Mozilla Firefox\firefox.exe' -? ; '宾果游戏'
    【解决方案3】:

    总是有 cmd。如果您在引用 start-process 的参数时遇到问题,可能会不那么烦人:

    cmd /c start /wait notepad
    

    或者

    notepad | out-host
    

    【讨论】:

      【解决方案4】:

      更进一步,您甚至可以动态解析

      例如

      & "my.exe" | %{
          if ($_ -match 'OK')
          { Write-Host $_ -f Green }
          else if ($_ -match 'FAIL|ERROR')
          { Write-Host $_ -f Red }
          else 
          { Write-Host $_ }
      }
      

      【讨论】:

        【解决方案5】:

        有些程序不能很好地处理输出流,使用管道到Out-Null 可能不会阻塞它。
        Start-Process 需要-ArgumentList 开关来传递参数,不太方便。
        还有另一种方法。

        $exitCode = [Diagnostics.Process]::Start(<process>,<arguments>).WaitForExit(<timeout>)
        

        【讨论】:

        • 多个参数在该调用中如何工作?它们是如何划分的?如何处理各种嵌套字符串转义?太棒了!
        • @AnneTheAgile doc 使用空格分隔参数,字符转义使用反斜杠
        • ty @ifree,我确实让 testcomplete 以这种方式运行!我在空格分隔的参数列表周围使用了单引号。[1];但是现在回显 $exitcode=false,这不是我从该过程中返回的代码? [1] $exitCode = [Diagnostics.Process]::Start("c:\Program Files (x86)\SmartBear\TestComplete 10\Bin\TestComplete.exe",'"c:\Users\ME\Documents\TestComplete 10 Projects\hig4TestProject1\hig4TestProject1.pjs" /run /project:myProj/test:"KeywordTests|zTdd1_Good" /exit').WaitForExit(60)
        • Start-Process -Wait 在关闭应用程序后需要很长时间(如一分钟)才能返回脚本执行。这需要几秒钟。
        【解决方案6】:

        包含选项 -NoNewWindow 会给我一个错误:Start-Process : This command cannot be executed due to the error: Access is denied.

        我可以让它工作的唯一方法是打电话:

        Start-Process <path to exe> -Wait
        

        【讨论】:

        • 通常意味着它需要以管理员身份运行。管理员权限提升需要打开一个新窗口。无法将管理命令连接到非管理控制台。
        【解决方案7】:

        如果你使用Start-Process &lt;path to exe&gt; -NoNewWindow -Wait

        您还可以使用-PassThru 选项来回显输出。

        【讨论】:

        • 请注意,-PassThru 不会回显 output(根据定义,非控制台应用程序不会产生控制台输出),它会输出一个 System.Diagnostics.Process 实例表示新启动的进程,因此您可以检查其属性并等待它稍后退出。
        【解决方案8】:

        只需使用“等待过程”:

        "notepad","calc","wmplayer" | ForEach-Object {Start-Process $_} | Wait-Process ;dir
        

        任务完成

        【讨论】:

        • 它不适用于 PowerShell 7.1.4(在 Windows 10 上)。
        猜你喜欢
        • 2018-04-03
        • 1970-01-01
        • 2023-03-06
        • 2019-07-16
        • 2020-08-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-03-15
        相关资源
        最近更新 更多