Powershell对cmd.exe的等待因环境而异
请考虑powershell命令:Powershell对cmd.exe的等待因环境而异,powershell,Powershell,请考虑powershell命令: cmd.exe "/c start notepad.exe" 使用powershell.exe(控制台),此命令在启动cmd/notepad进程后立即完成,不等待notepad/cmd退出。如果我想让它等待完成,我必须通过管道将输出设置为Out Null 使用powershell ISE,此命令将阻止执行,直到关闭记事本/cmd 此外,如果我使用System.Diagnostics.process和redirect standard output在powers
cmd.exe "/c start notepad.exe"
使用powershell.exe(控制台),此命令在启动cmd/notepad进程后立即完成,不等待notepad/cmd退出。如果我想让它等待完成,我必须通过管道将输出设置为Out Null
使用powershell ISE,此命令将阻止执行,直到关闭记事本/cmd
此外,如果我使用System.Diagnostics.process和redirect standard output在powershell.exe中运行的脚本中创建一个新进程(powershell.exe),脚本现在会阻止执行,直到notepad/cmd关闭。如果我不重定向输出,它不会阻止执行
但是,如果我使用c#创建一个具有相同设置/启动信息的新进程,并使用重定向输出运行相同的脚本,它不会阻止执行
我在这里不知所措。显然,它和执行和输出的设置有关,也可能和“cmd.exe”有关。我希望有人能以不同的方式理解这些案件背后的基本情况。我知道ISE和cmd.exe不完全受支持,但我不知道为什么其他3个不一致
为什么脚本不以相同的行为运行(尤其是powershell控制台脚本),我如何让它们运行
编辑: 经过一些故障排除,我能够让所有powershell.exe版本运行相同的版本(ISE对我来说并不重要)。
cmd.exe”/c start notepad.exe“
阻止执行的奇数球是在powershell中创建新进程以使用System.Diagnostics.process
运行powershell.exe时。如果输出被重定向(我使用System.Diagnostics.Process
的原因是,Start Process
不支持重定向,只支持重定向到文件),那么对Process对象调用WaitForExit()
会导致阻塞发生
只需将
WaitForExit()
替换为Wait Process
(以及进程ID),即可使新powershell.exe中运行的powershell脚本按预期执行,并在运行命令后退出。希望此信息与@mklement0 answer相结合,足以让其他任何人遇到类似问题。在常规控制台和ISE中获得可预测的行为:
- 异步启动GUI应用程序(立即返回提示符/继续执行脚本):
notepad.exe
- 直接调用记事本使其异步运行,因为它是一个GUI子系统应用程序
- 如果您仍然希望跟踪流程,并在终止时检查流程是否仍在运行以及退出代码是什么,请使用
,这将使-PassThru
返回一个实例:启动流程
$process=启动进程-PassThru notepad.exe
稍后将告诉您进程是否仍在运行$process.HasExited
- 退出后,
会告诉您退出代码(在GUI应用程序中可能不会告诉您太多)$process.ExitCode
- 要同步等待(在某个点):
- 使用
等待(无限期)进程终止Wait Process$Process.ID
- 添加以秒为单位的
值以限制等待时间;如果进程未在超时时间内终止,则会报告非终止错误,导致-Timeout
反映$?
$False
- 使用
- 同步启动GUI应用程序(阻止,直到应用程序终止):
启动进程-等待notepad.exe
告知等待,直到创建的进程终止;这相当于-Wait
cmd/c'start/wait notepad.exe'
请注意,对于控制台子系统应用程序(例如,
findstr.exe
),同步执行是默认的<代码>启动进程仅适用于GUI应用程序,包括显式创建新的控制台窗口以在中运行命令
要异步运行控制台应用程序或shell命令(不打开新的控制台窗口),可以使用以下选项:
- [首选]用于启动命令,并在以后接收其输出/成功状态
$j=Start Job{sleep 2;'hi'}
- 要同步等待此作业完成(并自动删除),请使用
接收作业-等待-自动删除作业$j
- 在PowerShell Core中,您可以使用更简单的
&代码>语法(如中所示 类似于POSIX的Unix shell,如
)代替bash
;e、 g:Start Job
$j=&{sleep 2;'hi!'}&
- [不建议]您可以使用类似于
的方法,但这是不明智的:启动进程-非Windows powershell-Args…
- 通过
将shell命令传递给Start Process
,需要基于模糊规则的复杂引用-请参阅我的背景信息powershell
- 默认情况下,由application/shell命令生成的任何stdout和stderr输出都将异步地到达当前控制台,并与您正在交互执行的操作交织在一起
- 虽然您可以使用
和-RedirectStandardOutput
(以及通过-RedirectStandardError
的stdin输入)将这些流重定向到文件,并且您可以使用-RedirectStandardInput
获取流程信息对象以确定流程的状态和退出代码,-PassThru
启动作业
- 通过