2012-05-11 2 views
1

При открытии диспетчера задач Windows для просмотра PID всех открытых процессов я вижу, что все открытые вкладки в моем браузере Chrome имеют свой собственный уникальный PID, однако я получаю тот же PID, независимо от того, какая вкладка в фокусе при использовании:C# Как получить уникальный PID для каждой вкладки браузера во внешнем браузере, т.е. Chrome/Firefox/IE

[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); 

Кто-нибудь знает, как однозначно идентифицировать вкладки браузера? И еще дальше, кто-нибудь знает, как поймать событие, когда вкладки браузера меняют состояние или фокус? Любой браузер - Chrome, Firefox, IE

Ниже мой полный код поймать событие WinEventHook, когда на переднем плане изменения окна:

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"; 

    } 
} 

}

+0

Chrome - единственный браузер, о котором я знаю, который на самом деле использует разные процессы для каждой вкладки. Большинство браузеров используют несколько потоков. Я считаю, что причина, по которой вы всегда получаете тот же процесс из GetForegroundWindow(), состоит в том, что это вернет основной процесс chrome, а не процесс для открытой вкладки. – firthh

+0

@firthh: IE9 также является многопроцессорным. –

+0

Хотя IE9 имеет несколько процессов, он не использует один процесс для каждой вкладки - по соображениям производительности он содержит несколько вкладок для каждого процесса. – snemarch

ответ

3

Вы не собираетесь быть в состоянии сделать то, что вы хотите - по крайней мере, не в надежном режиме.

Браузеры реализованы по-разному. FireFox и более старые версии IE используют однопроцессорную модель, IE9 - многопроцессорный, но по производительности несколько групп для каждого процесса, а Chrome делает один процесс за вкладку. Другие браузеры/версии браузера делают все, что они хотят (но, скорее всего, однопроцессорный). Вам нужно будет написать конкретный код для браузеров, которые вы хотите поддержать, и вы будете иметь дело с довольно подробными деталями реализации.

Для Chrome iirc модель представляет собой одно «окно хоста», которое обрабатывает рендеринг. Процессы обработки каждой вкладки - это «рабочие процессы», с обменом сообщения между хостом и рабочими ... Если у Chrome нет официального API для получения PID для рабочих процессов, то не беспокойтесь :)

+0

Хорошо, спасибо. Думаю, в качестве второго подхода мне придется попытаться использовать подход таймера и проверить URL-адрес браузера каждые пару секунд для изменения. – MElliott

+0

Я немного новичок в программировании на C# .net, но то, что я действительно пытаюсь сделать log, сколько времени тратится на определенный URL. Таким образом, с приведенным выше кодом я могу обнаружить, когда браузер получает фокус, а затем, когда браузер является фокусом, запустите таймер, чтобы постоянно проверять URL-адрес и время регистрации, если URL-адрес совпадает с тем, который я ищу. и таймер остановки, когда браузер теряет фокус. Я бы предпочел использовать для этого события, но это не похоже на то, что это возможно. Пожалуйста, дайте мне знать, если у вас есть какие-либо указания или предложения для меня. – MElliott

+0

Если вы хотите сделать это надежно, вы должны задуматься о написании расширений/аддонов браузера ... но вам нужно будет написать что-то для каждого главного браузера :) – snemarch

Смежные вопросы