繁体   English   中英

如何在 Powershell 中获取新创建的 Firefox window 的正确 PID?

[英]How to get the proper PID of a newly created Firefox window in Powershell?

这是我遇到的问题的一个非常简单的示例:

$process = Start-Process 'C:\Program Files\Mozilla Firefox\firefox.exe' -argumentlist "-new-window https://google.com -foreground" -PassThru

Write-Host $process.Id

firefox window 将按预期启动和工作,它会返回一个进程 ID,但是当我实际检查正在运行的进程时,我看不到该 PID 的任何结果。

我试着添加这个只是为了看看,

while (-not $process.HasExited){
    Write-Host "..."
}

Write-Host $process.HasExited

看起来该进程在退出前确实运行了几毫秒。

我认为这可能与 Firefox 如何处理它自己的进程有关。 因为我用其他一些随机应用程序测试了类似的设置,它们都按预期工作。

关于 Firefox 时如何解决这个问题的任何想法?

有几个挑战需要克服:

  • 最终呈现实际浏览器 window 的firefox进程与最初启动的进程不同。 也就是说,正如您所观察到的,已启动的进程会产生其他进程,并且它自己会快速退出。

  • 正如Olaf指出的那样,现代浏览器通常会启动多个非瞬态进程,因此挑战在于如何识别代表浏览器 window 的进程。

  • 浏览器可能会重用现有进程,因此单个进程可以呈现多个 windows / 选项卡,关闭其中一个不会终止整个进程。

    • 如果您需要确保使用专用的新流程,您有两种选择:

      • (a) 确保没有预先存在的 Firefox 实例正在运行,要么通过出错,要么 - 如果您的用例可接受 - 首先强制终止所有现有实例( Stop-Process -Name firefox )。
      • (b) 通过更多的努力,创建一个专用的临时 Firefox配置文件,您可以使用-new-instance选项启动它,它允许多个独立的 Firefox 实例同时运行,并且可以单独跟踪其生命周期。

以下 - 繁琐 - 解决方案实现了选项(b):

  • 如果没有找到firefox进程,则不用担心创建独立实例,Firefox可以正常启动。

  • 否则,将创建一个临时配置文件,并通过-new-instance-profile选项启动,以确保使用进程来呈现新浏览器 window。

  • 启动初始进程后,循环直到出现firefox进程,该进程稍后启动并且具有非空的 window title ,然后假定它是真正感兴趣的进程。

  • 然后,您可以等待此过程的终止,以了解专用浏览器 window 何时关闭。 如果必须创建临时配置文件,则之后会对其进行清理。

# Comment this statement out to silence the verbose messages below.
$VerbosePreference = 'Continue'

$now = Get-Date
$url = 'https://example.org'  # URL to open.

# Launch a (new) Firefox instance.
if ($alreadyRunning = [bool] (Get-Process -ErrorAction Ignore firefox)) {
  # Determine the path for a temporary profile with a unique name.
  $tempProfilePath = Join-Path ([IO.Path]::GetTempPath()) ([datetime]::utcnow.tostring('o') -replace '\D')
  Write-Verbose  "Firefox is already running. Creating temp. profile $tempProfilePath..."
  # Note: Creating an empty directory for the profile is seemingly enough.
  $null = New-Item -Type Directory $tempProfilePath
  Write-Verbose "and starting a new instance with it..."
  Start-Process firefox "-new-instance -profile $tempProfilePath $url"
} else {
  Write-Verbose 'Firefox isn''t running. Starting normally...'
  Start-Process firefox $url
}

# Find the newly launched process that is the actual browser window.
Write-Verbose 'Waiting for a recently launched Firefox process with a nonempty window title to appear...'
while (-not (
  $ps = Get-Process firefox | 
    Where-Object StartTime -gt $now |
      Where-Object MainWindowTitle
)) {
  Write-Host -NoNewLine . 
  Start-Sleep -MilliSeconds 500 
}
Write-Host

Write-Verbose "Found. Waiting for process to exit..."
$ps.WaitForExit()

Write-Verbose 'Process has exited.'

if ($alreadyRunning) {
  Write-Verbose "Cleaning up temporary profile $tempProfilePath..."
  do {
    # The profile dir. is typically held on to for a little while longer by associated processes that may not have terminated yet.
    Start-Sleep -MilliSeconds 200
    Remove-Item -ErrorAction Ignore -Literalpath $tempProfilePath -Recurse -Force
  }
  while (Test-Path -LiteralPath $tempProfilePath)
}

感谢@mklement0 的工作,在您的情况下,您可以使用父进程 ID。

我使用 WMI 获取父进程,但它适用于第一次启动。

$parentProcess = Start-Process 'C:\Program Files\Mozilla Firefox\firefox.exe' -argumentlist "-new-window https://google.com -foreground" -PassThru
$childProcess = get-process -id $(Get-CimInstance -Class Win32_Process -Filter "Name = 'firefox.exe'"  | where {$_.ParentProcessId -eq $parentProcess.id}).ProcessId
# effectively stop the child
$childProcess | Stop-Process

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM