开始进程并等待仅父进程完成
开始进程并等待仅父进程完成
我正在使用PowerShell语法:
Start-Process -FilePath $file -ArgumentList $argList -NoNewWindow -Wait
被启动的进程是一个安装程序,它安装了一个Windows服务,然后启动该服务,然后进程停止。问题是,即使进程成功完成并且进程已经退出(我可以在任务管理器中看到),我的脚本仍然无限期地挂起。当我在没有PowerShell的命令行中运行它时,它在不到一分钟内完成。显然,它仍在等待,因为有一个从原始进程生成的子进程。如何告诉PowerShell只等待初始进程($file),而不等待任何子进程?
谢谢
过去,我曾经做过相反的事情,即想要等待某个进程启动才能继续执行,我使用了WMI事件来实现。你可以尝试看看是否可以使用相同的技术来解决你的问题:
# 启动一个要跟踪的进程 Start-Process "Notepad.exe" # 使用WMI跟踪进程退出事件 Register-WmiEvent -Query "SELECT * FROM __instancedeletionevent WITHIN 5 WHERE targetinstance isa 'win32_process'" ` -SourceIdentifier "WMI.ProcessDeleted" ` -Action { if($eventArgs.NewEvent.TargetInstance.Name -eq "Notepad.exe") { Write-Host "Notepad退出!" # 触发一个事件来通知完成 New-Event "PowerShell.ProcessDeleted" -Sender $sender -EventArguments $EventArgs.NewEvent.TargetInstance | Out-Null } } | Out-Null # 等待表示任务完成的事件(超时时间为10分钟) Wait-Event -SourceIdentifier "PowerShell.ProcessDeleted" -Timeout 600 | Out-Null # 移除我们创建的任何事件 Get-Event -SourceIdentifier "PowerShell.ProcessDeleted" -ErrorAction SilentlyContinue | Remove-Event # 注销事件监视器 Unregister-Event -Force -SourceIdentifier "WMI.ProcessDeleted"
只需将"Notepad.exe"替换为你的安装程序进程名称,并删除对Write-Host的调用(或者替换为更实用的内容)。如果在10分钟内关闭了Notepad(根据需要进行调整),你应该会看到一条消息,否则脚本将继续执行,以免无限期地挂起。
非常聪明!最终,我决定使用了贴出的New-Object System.Diagnostics.Process方法来解决问题。
这个问题的出现是因为在执行父进程时,希望能等待子进程完成后再继续执行其他操作。下面是解决方法:
一种解决方法是在脚本中使用等待命令(Start-Sleep 60或类似命令),等待一段时间后再执行其他操作。这种方法适用于安装时间较短且简单的情况。
另一种解决方法是在开始安装之前,先记录正在运行的msiexec进程,然后循环每隔60秒左右检查新的进程是否已经结束。如果安装过程中还调用了子安装程序,则问题会更加复杂。
另外一种解决方法是循环每隔60秒左右检查WMI Win32_Product类是否存在正在安装的产品实例。这种方法的成功程度取决于具体的安装和环境。
解决这个问题需要根据具体的安装和环境情况来选择合适的解决方法。
问题出现的原因:问题的出现是因为在使用PowerShell执行程序时,希望能够使用Start-Process启动一个子进程,并且在子进程执行完成后等待父进程继续执行。然而,在上述代码中,并没有等待子进程执行完成的步骤。
解决方法:为了解决这个问题,需要在子进程启动后,加入等待子进程执行完成的步骤。可以使用$p.WaitForExit()来实现等待子进程执行完成的功能。
以下是修改后的代码:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo $pinfo.FileName = $file $pinfo.UseShellExecute = $false $pinfo.Arguments = $argList $p = New-Object System.Diagnostics.Process $p.StartInfo = $pinfo $p.Start() | Out-Null $p.WaitForExit() Write-Host "exit code: " + $p.ExitCode
通过添加$p.WaitForExit(),可以确保子进程执行完成后,才会继续执行父进程的后续代码。这样就实现了"Start-Process And Wait For Parent Process Only"的需求。