2008-11-07 12 views
3

J'ai accidentellement supprimé la compatibilité Win2K d'une application en utilisant GetProcessID.Alternative à GetProcessID pour Windows 2000

Je l'utilise comme ceci, pour obtenir le HWND principal pour l'application lancée.

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) 
... 
} 

Des idées comment la même fonction pourrait être réalisée sur Win2K?

Répondre

6

Il y a une fonction 'tri-de non prise en charge': ZwQueryInformationProcess(): voir

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

Cela vous donnera le numéro de processus (entre autres), compte tenu de la poignée. Cela ne garantit pas de fonctionner avec les futures versions de Windows, donc je suggère d'avoir une fonction d'assistance qui teste la version du système d'exploitation et utilise ensuite GetProcAddress() pour appeler GetProcessId() pour XP et plus, et ZwQueryInformationProcess() pour Win2K seulement .

-1

Non, ce n'est pas ZwQueryInformationProcess() Il est NtQIP et bien sûr cela fonctionne pour toutes les versions depuis NT 3.5 et vous n'avez pas besoin de tester OS du tout

+0

Je suppose que vous vouliez dire NtQueryInformationProcess() - Quelle est la différence entre cela et ZwQueryInformationProcess()? – Roddy

+0

il ne semble y avoir aucune différence entre ZwQueryInformationProcess() et NtQueryInformationProcess(). Sur Vista, ils ont tous les deux la même adresse. Les deux étant marqués potentiellement indisponibles, tester le système d'exploitation * est * nécessaire pour une compatibilité future. – Roddy

+0

En mode noyau, ils sont différents. – ChristianWimmer

5

droit de DavidK. S'il vous plaît voir le commentaire dans la documentation ZwQueryInformationProcess:

[ZwQueryInformationProcess peuvent être modifiés ou non disponibles dans le futur versions de Windows. Applications doivent utiliser les autres fonctions répertoriées dans cette rubrique.]

Cela signifie que Microsoft peut choisir de supprimer à tout moment à l'avenir, brisant ainsi votre application. Je considère fortement que vous suivez les conseils de DavidK et utilisez ZwQueryInformationProcess sur les systèmes d'exploitation qui ne supportent pas GetProcessID et utilisez GetProcessID sur les systèmes d'exploitation qui le supportent (XP SP1 et plus).

2

Merci à DavidK et Larry - Voici ma solution finale. Le traitement complet des erreurs est laissé comme un exercice pour le lecteur.

Notez que plutôt que de vérifier spécifiquement la version du système d'exploitation, je tente de lier dynamiquement aux fonctions. La liaison statique signifierait que l'application échouerait simplement à charger si la procédure n'était pas disponible.

Cela a été essayé avec succès sur Win2K et 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; 
    } 
}