【问题标题】:Start-Process And Wait For Parent Process Only仅启动进程并等待父进程
【发布时间】:2018-03-22 18:47:06
【问题描述】:

我正在使用 PowerShell 语法:

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

正在启动的进程是一个安装程序,它安装 Windows 服务,然后启动该服务,然后该进程停止。发生的事情是我的脚本无限期挂起,即使在进程成功完成并且进程退出之后(正如我在任务管理器中看到的那样。当我从命令行运行它时,没有 PowerShell,不到一分钟就完成了)。显然,它仍在等待,因为有一个从原始进程产生的子进程。如何告诉 PowerShell 只等待初始进程 ($file) 而不是任何子进程?

谢谢

【问题讨论】:

  • 您可以使用 while 循环等待 Windows 服务存在,而不是 -Wait。睡到它为止。

标签: powershell process


【解决方案1】:

最后,我决定简单地使用 .NETy 方式来实现,尽管我更喜欢 Powershelly 方式。下面的代码是从https://stackoverflow.com/a/8762068/1378356复制过来的:

$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

这种方法没有问题。

【讨论】:

    【解决方案2】:

    我多年来一直在处理这个问题。一般来说,如果安装非常简短和简单,我只会在脚本中等待(Start-Sleep 60 或其他)。但是,如果安装运行的时间非常可变,那么我实际上会在开始安装之前对正在运行的 msiexec 进程进行编目,然后每 60 秒左右循环并检查所有新进程是否已结束。如果安装调用实际的子安装,它会变得更加棘手。根据安装情况,我使用的另一种或多或少成功的方法是每 60 秒左右再次循环检查一次,以查看针对 WMI Win32_Product 类的查询是否具有正在安装的产品的实例。您几乎必须针对安装和您的环境定制解决方案。

    【讨论】:

      【解决方案3】:

      在过去,我做了相反的事情,我想等到某个进程开始才能继续,我使用 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。
      猜你喜欢
      • 2013-10-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-10-11
      • 1970-01-01
      • 2011-07-16
      • 1970-01-01
      相关资源
      最近更新 更多