When opening Windows Task Manager to view the PID of all open processes, I can see that all the open tabs in my Chrome browser have their own unique PID, however I get the same PID no matter what tab is in focus when using:
[DllImport("user32.dll")]
static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
IntPtr hwnd = GetForegroundWindow();
GetWindowThreadProcessId(hwnd, out pid);
Does anyone know how to uniquely identify browser tabs? And even further, does anyone know how to catch an event when the browser tabs change state or focus? Any browser – Chrome, Firefox, IE
Below is my full code catching the WinEventHook event when the foreground window changes:
using System;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.IO;
namespace focusWindow2
{
public partial class Form1 : Form
{
[DllImport("user32.dll")]
static extern IntPtr SetWinEventHook(SystemEvents eventMin, SystemEvents eventMax, IntPtr hmodWinEventProc,
SystemEventHandler lpfnWinEventProc, uint idProcess, uint idThread, uint dwFlags);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool UnhookWinEvent(IntPtr hWinEventHook);
[DllImport("user32.dll")]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
delegate void SystemEventHandler(IntPtr hWinEventHook, SystemEvents @event, IntPtr hwnd, int idObject, int idChild,
uint dwEventThread, uint dwmsEventTime);
enum SystemEvents
{
ForegroundWindowChanged = 0x3 // EVENT_SYSTEM_FOREGROUND - The only flag we care about
}
IntPtr _WinEventHook;
SystemEventHandler _WinEventHookHandler;
public Form1()
{
InitializeComponent();
// Create the handler
_WinEventHookHandler = new SystemEventHandler(WinEventHook);
// Set the hook
_WinEventHook = SetWinEventHook(SystemEvents.ForegroundWindowChanged, SystemEvents.ForegroundWindowChanged,
IntPtr.Zero, _WinEventHookHandler, 0, 0, 0);
this.FormClosing += delegate
{
UnhookWinEvent(_WinEventHook);
};
}
private void WinEventHook(IntPtr hWinEventHook, SystemEvents @event, IntPtr hwnd, int idObject, int idChild,
uint dwEventThread, uint dwmsEventTime)
{
uint pid = 0;
GetWindowThreadProcessId(hwnd, out pid);
Process p = Process.GetProcessById((int)pid);
string procName = Path.GetFileName(p.ProcessName);
textBox1.Text += procName + " " + pid + "\r\n";
}
}
}
You aren’t going to be able to do what you want to – at least not in a reliable way.
The browsers are implemented differently. FireFox and older IE versions use a one-process model, IE9 is multiprocess but groups several tabs per process for performance reasons, and Chrome does one process per tab. Other browsers/browser versions do whatever they want (but most likely single-process). You’d have to write specific code for the browsers you want to support, and you’d be dealing with pretty deep-down implementation details.
For Chrome, iirc the model is one “host window” that handles the rendering. The processes for handling each tab are “worker processes”, with communication back and forth between the host and workers… If Chrome doesn’t have an official API for getting PIDs for the worker processes, then don’t bother 🙂