Search code examples
c#processwindowpinvokeforeground

How to use GetForeGroundWindow() to get newly launched application window handle in C#?


I am trying to capture a newly launched application using GetForegroundWindow() using P/Invoke in C#. However, all i get is explorer.exe window handle instead of the actual process window handle (such as notepad.exe or wordpad.exe) that was launched.

Actually i am trying to log user entered text when user opens "notepad" at the same time i want to get the actual handle of the "notepad" instance (if multiple notepad instances are open) in which user is attempting to write something.

i.e I launch notepad.exe from start menu on Windows 7 Ultimate x64 with my C#.Net based application running for keys pressed. I have setup application key hooks in my application so that on text changed event, the application attempts to get the foreground window. The problem is: It gets explorer.exe instead of notepad.exe.

The code works for already-open windows perfectly but it doesn't work for newly launched instances of any application such as chrome, notepad, wordpad or any other. Instead of logging text against the correct application, it logs text for explorer.exe. Here is my code:

    private string GetActiveWindowTitle()
    {
        const int nChars = 256;
        IntPtr handle = IntPtr.Zero;
        StringBuilder Buff = new StringBuilder(nChars);
        handle = GetForegroundWindow();

        if (GetWindowText(handle, Buff, nChars) > 0)
        {
            return Buff.ToString();
        }
        return null;
    }
    Process GetActiveProcess()
    {
        Process[] AllProcess = Process.GetProcesses();
        String title = GetActiveWindowTitle();

        foreach (Process pro in AllProcess)
        {
            if (title.Equals(pro.MainWindowTitle))
            {
                return pro;
            }
        }
        return Process.GetCurrentProcess();
    }

    string GetActiveProcessFileName()
    {
        IntPtr hwnd = GetForegroundWindow();
        SetForegroundWindow(hwnd);
        uint pid;
        GetWindowThreadProcessId(hwnd, out pid);
        Process p = Process.GetProcessById((int)pid);
        //p.MainModule.FileName.Dump();
        return p.ProcessName;
    }

    ProcessInfo GetActiveProcessInfo()
    {
        IntPtr hwnd = GetForegroundWindow();

        const int nChars = 256;
        StringBuilder Buff = new StringBuilder(nChars);
        uint pid;
        GetWindowThreadProcessId(hwnd, out pid);
        Process p = Process.GetProcessById((int)pid);
        ProcessInfo pi = new ProcessInfo();
        if (GetWindowText(hwnd, Buff, nChars) > 0)
        {
            pi.ProcessTitle = Buff.ToString();
        }
        pi.ProcessName = p.ProcessName;
        pi.ProcessHandle = (int)p.MainWindowHandle;

        return pi;
    }

GetActiveProcessInfo returns explorer.exe instead of correct application i.e notepad.exe because the GetForegroundWindow() read explorer.exe as foreground window. The same code reads the correct application window when i type in existing open applications and donot launch a new instance of teh application.

I read somewhere that there is some race-condition problem. if this is the case, how can i solve this?

Please help me. I am really stuck on this very long.

Thanks.


Solution

  • Ok. Guys. The problem was not with GetForegroundWindow(). Maybe that's why i didnt get any answer for that. I debugged the issue in detail and located the problem. The answer can be found here with corrected code.

    Solution with Code