Получение имени исполняемого файла из дескриптора в Windows x64 - PullRequest
2 голосов
/ 01 ноября 2009

У меня есть приложение c #, которое скомпилировано как x86, поэтому оно работает как 32-битное приложение на Windows 7 x64. Пока приложение работает, мне нужно определить имя исполняемого файла активного окна. На Winodws XP следующий код работал нормально (получение имени файла процесса из дескриптора активного окна). На x64 он сообщает имя только 32-битных процессов (возвращая мусор для других, вероятно, потому что я не проверяю возвращенные данные). Я передаю дескриптор активного окна, которое я получил с помощью API GetForegroundWindow.

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

Могу ли я получить эту информацию из 32-битного процесса в 64-битной среде? Благодарю. Andrea

Ответы [ 2 ]

1 голос
/ 22 сентября 2010

Так как нет проверки ошибок: прошли ли вы код и убедились, что различные вызовы API до GetModuleFileNameEx возвращают разумную информацию? Кроме того, вы должны определить некоторые символические константы вместо жесткого кодирования спецификатора доступа 1040.

Вы пробовали использовать System.Diagnostics.Process.GetProcessById()? Он имеет свойство MainModule, откуда вы можете получить FileName. Хотя стоит попробовать.

Некоторое беглое гугление указывает на то, что вы, возможно, столкнетесь головой со стенами x64 и WoW64. Одним из таких более полезных результатов поиска было this - сводка: check QueryFullProcessImageName .

EDIT:

Очевидно, WMI может преодолеть разрыв WoW64, позволяя вам сделать SELECT ExecutablePath FROM Win32_Process WHERE ProcessID = %ProcessID%. По моему опыту, WMI несколько тяжел, поэтому это будет последнее средство.

1 голос
/ 03 ноября 2009

Между прочим, есть API GetWindowModuleFileName , который делает все, что вам нужно, за один вызов. Я еще не проверял, работает ли он лучше в вашем сценарии.

...