Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

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?

like image 563
ryan.kom Avatar asked Oct 20 '25 08:10

ryan.kom


1 Answers

There are several challenges to overcome:

  • 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.

    • If you need to ensure that a dedicated, new process is used, you have two options:

      • (a) Make sure that no preexisting Firefox instance is running, either by erroring out, or - if acceptable for your use case - by forcefully terminating all existing instances first (Stop-Process -Name firefox).
      • (b) With significantly more effort, create a dedicated, temporary Firefox profile that you can launch with the -new-instance option, which allows multiple independent Firefox instances to run concurrently and whose lifetime can be tracked separately.

The following - cumbersome - solution implements option (b):

  • If no firefox process is found, there is no concern about creating independent instances, and Firefox can be launched normally.

  • Otherwise, a temporary profile is created, and launched via the -new-instance and -profile options to ensure that a new process will be used to present the new browser window.

  • 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.

  • You can then wait for the termination of this process to know when the dedicated browser window has been closed. If a temporary profile had to be created, it is cleaned up afterwards.

# 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)
}
like image 111
mklement0 Avatar answered Oct 22 '25 23:10

mklement0



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!