ChatGPT解决这个技术问题 Extra ChatGPT

如何告诉 PowerShell 在开始下一个命令之前等待每个命令结束?

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

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

这就是我所拥有的...

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

C
Cristian Ciupitu

通常,对于内部命令,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 会暂停,直到父进程产生的所有子进程都完成,即使父进程在它们之前终止。这导致了我们的安装程序问题。
对于僵尸评论很抱歉,但如果有人试图为 VMware 复制此内容,请使用 PowerCLI 并使用 Wait-Tools 或使用 Invoke-VMScript 进行操作,直到获得所需的响应。
C
Cristian Ciupitu

除了使用 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' -? ; '答对了'
F
Flaviofire

只需使用“等待过程”:

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

工作完成


它不适用于 PowerShell 7.1.4(在 Windows 10 上)。
S
Sandy Chapman

如果您使用 Start-Process <path to exe> -NoNewWindow -Wait

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


请注意,-PassThru 不会回显 output(根据定义,非控制台应用程序不会产生控制台输出),它会输出代表新启动进程的 System.Diagnostics.Process 实例,因此您可以检查它的属性并等待它稍后退出。
I
Igor Popov

有些程序不能很好地处理输出流,使用管道到 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 在关闭应用程序后需要很长时间(如一分钟)才能返回脚本执行。这花了几秒钟。
t
twasbrillig

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

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

Start-Process <path to exe> -Wait

通常意味着它需要以管理员身份运行。管理员权限提升需要打开一个新窗口。无法将管理命令连接到非管理控制台。
J
Justin

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

例如

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

j
js2010

总是有cmd。

cmd /c start /wait notepad

或者

notepad | out-host