Home > OS >  How to get the proper PID of a newly created Firefox window in Powershell?
How to get the proper PID of a newly created Firefox window in Powershell?

Time:02-28

Here is a very simple example of the problem I am experiencing:

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

Write-Host $process.Id

The firefox window will start and work as expected, it will return a process id, but when I actually check the running processes, I see no results for that PID.

I tried adding this just to see,

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

Write-Host $process.HasExited

And it looks like the process does run for maybe a couple milliseconds before it exits.

I'm thinking this may have something to do with how Firefox handles it's own processes. Because I tested a similar setup with some other random apps and they all worked as expected.

Any ideas on how to work around this when it comes to Firefox?

CodePudding user response:

There are several problems:

  • The firefox process that ends up presenting the actual browser window is different from the one that is initially launched. That is, as you've observed, the launched process spawns other processes and itself exits quickly.

  • As Olaf points out, modern browsers typically launch multiple non-transient processes, so the challenge is how to identify the one that represent the browser window.

  • Browsers may reuse existing processes, so a single process can present multiple windows / tabs, and closing one of them won't terminate the process as a whole.

You can try the following - cumbersome - workaround:

  • Launch the initial firefox process with the -new-instance option, to ensure that a new process will be used to present the new browser window.

    • Caveat: Due to what I presume is a bug, on my W10 H2020 machine with Firefox 97.0.1, using -new-instance when another window is already open causes a delay and eventually pops up a message Firefox is already running, but is not responding. The old Firefox process must be closed to open a new window. - with OK and Cancel buttons; if you press OK, the existing window is killed, and only then is the new browser window opened.
  • After launching the initial process, loop until a firefox process appears that was launched later and has a nonempty window title, which is then presumed to be the real process of interest.

$now = Get-Date

Start-Process firefox '-new-instance'

while (-not (
  $ps = Get-Process firefox | 
    Where-Object StartTime -gt $now |
      Where-Object MainWindowTitle
)) { 
  Write-Verbose -Verbose 'Waiting for a recently launched Firefox process with a nonempty window with title to appear...'
  Start-Sleep -ms 500 
}

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

Write-Verbose -Verbose 'Process has exited.'

CodePudding user response:

Thanks to @mklement0 work, in your case you can use the parent Process ID.

I use WMI to get the parent process, but it works for the very first launch.

$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
  • Related