views:

294

answers:

2

I have a c# application that is compiled as x86 so it runs as a 32bit application on Windows 7 x64. While the application is running, I need to detect the executable name of the active window. On Winodws XP the following code worked fine (getting the process filename from the active window handle). On x64 it reports the name of only the 32bit processes (returning garbage for the others, probably because I'm not checking the data returned). I'm passing the handle of the active window that I got with the GetForegroundWindow API.

public static string GetProcessPathFromWindowHandle(IntPtr hWnd) {

        string filename = string.Empty;
        uint pid=0;
        Unmanaged.GetWindowThreadProcessId(hWnd, out pid);

        //error in Win64: returns strange characters for Win64 files
        const int nChars = 1024;
        StringBuilder filenameBuffer = new StringBuilder(nChars);
        IntPtr hProcess = Unmanaged.OpenProcess(1040, 0, pid);
        Unmanaged.GetModuleFileNameEx(hProcess, IntPtr.Zero, filenameBuffer, nChars);
        Unmanaged.CloseHandle(hProcess);

        filename = filenameBuffer.ToString();

        //Get the name of the Windows
        int length = Unmanaged.GetWindowTextLength(hWnd);
        StringBuilder sb = new StringBuilder(length + 1);
        Unmanaged.GetWindowText(hWnd, sb, sb.Capacity);

        Logger.Main.LogMessage("Window Title is: " + sb);
        Logger.Main.LogMessage("Process filename is: " + filename);
        return filename;
    }

Can I get that piece of information form a 32bit process in a 64bit environment? Thanks. Andrea

A: 

FYI, there's an API GetWindowModuleFileName that does all you want in a single call. I haven't checked if it works any better in your scenario though.

Mattias S
Is that API call any good? - http://support.microsoft.com/?id=228469
snemarch
A: 

Since there's no error checking: have you stepped through the code and verified that the various API calls before GetModuleFileNameEx return sensible information? Also, you should define some symbolic constats instead of hardcoding the 1040 access specifier.

Have you tried using System.Diagnostics.Process.GetProcessById()? It has a MainModule property from where you can grab FileName. Worth a shot, though.

Some cursory googling indicates you might be running your head into x64 vs. WoW64 walls, though. One of those more useful search results was this - summary: check out QueryFullProcessImageName.

EDIT:

Apparently WMI can bridge the WoW64 gap, allowing you to do SELECT ExecutablePath FROM Win32_Process WHERE ProcessID = %ProcessID%. In my experience WMI is somewhat heavy, so it would be a last resort.

snemarch