启动进程并等待父进程完成

5

我使用的是PowerShell语法:

Start-Process -FilePath $file -ArgumentList $argList -NoNewWindow -Wait

正在启动的过程是安装程序,它会安装一个Windows服务并启动该服务,然后进程停止。我的脚本无限期地挂起了,即使在进程成功完成且进程已退出之后(如任务管理器中所示)。当我在没有PowerShell的命令行中运行它时,它在不到一分钟内完成。显然,它仍在等待,因为有一个子进程从原始进程中衍生出来。如何告诉PowerShell仅等待最初的进程($file),而不是任何子进程?
谢谢。

1
你可以使用 while 循环等待 Windows 服务存在,而不是使用 -Wait。一直睡眠直到服务存在为止。 - Jelphy
3个回答

4

最终,我决定用.NET的方式去做,尽管我更喜欢PowerShell的方式。下面的代码是从https://dev59.com/aGoy5IYBdhLWcg3wHqeB#8762068复制的:

$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

这种方式没有问题。

0
过去,我曾经做过相反的事情,即我希望等待某个进程启动才能继续进行,并使用WMI事件来完成。尝试一下同样的技巧是否有所帮助也是值得一试的:
# Start a process to track
Start-Process "Notepad.exe"

# Get WMI to track process exits
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 exited!"

                                # Raise an event to notify completion
                                New-Event "PowerShell.ProcessDeleted" -Sender $sender -EventArguments $EventArgs.NewEvent.TargetInstance | Out-Null
                            }
                    } | Out-Null

# Wait for the event signifying that we completed the work (timeout after 10 min)
Wait-Event -SourceIdentifier "PowerShell.ProcessDeleted" -Timeout 600 | Out-Null

# Remove any events we created
Get-Event -SourceIdentifier "PowerShell.ProcessDeleted" -ErrorAction SilentlyContinue | Remove-Event

# Unregister the event monitor
Unregister-Event -Force -SourceIdentifier "WMI.ProcessDeleted"

只需将“Notepad.exe”替换为您的安装程序进程名称,并删除对Write-Host的调用(或者替换为更有用的内容)。如果您在10分钟内关闭了记事本(请进行调整以适应实际情况),则应该会看到一条消息,否则我们仍然继续执行脚本,以免脚本无限期挂起。

非常聪明!最终,我决定采用发布的 New-Object System.Diagnostics.Process。 - as9876

0
我已经处理这个问题多年了。一般来说,如果安装程序非常简短和简单,我会在脚本中加入等待时间(例如 Start-Sleep 60)。但是,如果安装程序运行的时间非常不确定,那么我实际上会在开始安装之前记录正在运行的 msiexec 进程,然后循环检查每隔 60 秒左右是否所有新进程都已结束。如果安装程序调用了实际的子安装程序,则情况会变得更加棘手。另一种方法是根据安装程序和您的环境,再次循环检查每隔 60 秒左右是否 WMI Win32_Product 类的查询有正在安装的产品实例,这种方法的成功程度因安装程序而异。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接