Альтернатива GetProcessID для Windows 2000 - PullRequest
4 голосов
/ 07 ноября 2008

Я случайно удалил совместимость Win2K из приложения, используя GetProcessID .

Я использую это так, чтобы получить основной HWND для запущенного приложения.

ShellExecuteEx(&info); // Launch application
HANDLE han = info.hProcess; // Get process

cbinfo.han = han;

//Call EnumWindows to enumerate windows....
//with this as the callback

static BOOL CALLBACK enumproc(HWND hwnd, LPARAM lParam)
{
  DWORD id;
  GetWIndowThreadProcessID(hwnd, &id);
  if (id == GetProcessID(cbinfo.han))
    setResult(hwnd)
 ...
}

Есть идеи, как можно реализовать ту же функцию на Win2K?

Ответы [ 4 ]

6 голосов
/ 07 ноября 2008

Существует функция «вроде неподдерживаемого»: ZwQueryInformationProcess (): см.

http://msdn.microsoft.com/en-us/library/ms687420.aspx

Это даст вам идентификатор процесса (среди прочего), учитывая дескриптор. Это не гарантирует работу с будущими версиями Windows, поэтому я бы предложил использовать вспомогательную функцию, которая проверяет версию ОС и затем использует GetProcAddress () для вызова либо GetProcessId () для XP и выше, и ZwQueryInformationProcess () только для Win2K .

5 голосов
/ 10 ноября 2008

DavidK прав. Пожалуйста, смотрите комментарий в документации ZwQueryInformationProcess:

[ZwQueryInformationProcess может быть изменен или недоступен в будущем версии Windows. Приложения следует использовать альтернативные функции перечислены в этой теме.]

Это означает, что Microsoft может в любое время удалить это, что приведет к повреждению вашего приложения. Я настоятельно рекомендую вам следовать совету DavidK и использовать ZwQueryInformationProcess на ОС, которые не поддерживают GetProcessID, и использовать GetProcessID на ОС, которые его поддерживают (XP SP1 и выше).

3 голосов
/ 11 ноября 2008

Спасибо DavidK и Larry - вот мое окончательное решение. Полная обработка ошибок оставлена ​​читателю в качестве упражнения.

Обратите внимание, что вместо того, чтобы специально проверять версию ОС, я пытаюсь динамически связываться с функциями. Статическое связывание будет означать, что приложение просто не сможет загрузиться, если процедура недоступна.

Это было успешно опробовано в Windows 2000 и Vista:

#include "Winternl.h"

typedef DWORD (WINAPI* pfnGetProcID)(HANDLE h);

typedef NTSTATUS (WINAPI* pfnQueryInformationProcess)(
    HANDLE ProcessHandle,
    PROCESSINFOCLASS ProcessInformationClass,
    PVOID ProcessInformation,
    ULONG ProcessInformationLength,
    PULONG ReturnLength);

DWORD MyGetProcessId(HANDLE h)
{
    static pfnQueryInformationProcess ntQIP = (pfnQueryInformationProcess) GetProcAddress(GetModuleHandle("NTDLL.DLL"),"NtQueryInformationProcess");
    static pfnGetProcID getPId  = (pfnGetProcID) GetProcAddress(GetModuleHandle("KERNEL32.DLL"),"GetProcessId");

    if ((ntQIP == NULL) && (getPId == NULL))
        throw Exception("Can't retrieve process ID : GetProcessID not supported");

    if (getPId != NULL)
        return getPId(h);
    else
    {
        PROCESS_BASIC_INFORMATION info;
        ULONG returnSize;
        ntQIP(h, ProcessBasicInformation, &info, sizeof(info), &returnSize);  // Get basic information.
        return info.UniqueProcessId;
    }
}
0 голосов
/ 07 ноября 2008

Нет, это не ZwQueryInformationProcess () Это NtQIP и, конечно, он работает для всех версий начиная с NT 3.5, и вам не нужно тестировать ОС вообще

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...