2009-12-28 9 views
10

J'ai créé un thread supplémentaire dans une petite application de test et je souhaite suspendre le thread principal à partir de ce thread supplémentaire. Le thread supplémentaire est créé via CreateRemoteThread à partir d'un processus externe.Traitement du thread principal du processus

Depuis SuspendThread a besoin d'un HANDLE pour le thread qui devrait être suspendu, je veux savoir comment obtenir ce HANDLE du code en cours d'exécution dans mon thread supplémentaire.

+0

Quelle est votre plate-forme cible? –

+0

C'est un processus de 32 bits sous Windows 7. J'utilise Visual Studio 2008 et donc Visual C++. – Etan

+0

Voulez-vous suspendre uniquement le fil "principal" ou tout? Qu'essayez-vous exactement d'accomplir? Il pourrait avoir une autre façon de le faire ... – cedrou

Répondre

6
DWORD GetMainThreadId() { 
    const std::tr1::shared_ptr<void> hThreadSnapshot(
     CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0), CloseHandle); 
    if (hThreadSnapshot.get() == INVALID_HANDLE_VALUE) { 
     throw std::runtime_error("GetMainThreadId failed"); 
    } 
    THREADENTRY32 tEntry; 
    tEntry.dwSize = sizeof(THREADENTRY32); 
    DWORD result = 0; 
    DWORD currentPID = GetCurrentProcessId(); 
    for (BOOL success = Thread32First(hThreadSnapshot.get(), &tEntry); 
     !result && success && GetLastError() != ERROR_NO_MORE_FILES; 
     success = Thread32Next(hThreadSnapshot.get(), &tEntry)) 
    { 
     if (tEntry.th32OwnerProcessID == currentPID) { 
      result = tEntry.th32ThreadID; 
     } 
    } 
    return result; 
} 
+0

Est-il garanti que le thread "principal" d'un processus sera toujours le premier dans un instantané? En outre, la question ne portait pas sur la façon d'identifier le fil principal; Il s'agissait de savoir comment obtenir une poignée, ce que cette réponse ignore. –

+5

Il n'y a même pas de garantie que le thread "principal" d'un processus existe toujours! Le thread principal du processus peut avoir fait un 'ExitThread'. –

14

Je ne pense pas qu'il y ait quelque chose qui différencie le thread principal des autres threads une fois que le processus a commencé. Toutefois, vous pouvez enumerate all threads in the process et utiliser GetThreadTimes pour trouver le fil avec la première heure de création. Appelez OpenThread pour obtenir un HANDLE à partir d'un ID de thread.

2

Un certain nombre de fonctions API utiles de ce type sont sous (bien sûr!) Tool Help suite. L'API CreateToolhelp32Snapshot() prendra un instantané des threads en cours d'exécution pour un processus spécifié.

// Take a snapshot of all running threads 
hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0); 
if(hThreadSnap == INVALID_HANDLE_VALUE) 
    return(FALSE); 

Code Exemple complet here.

Le retour struct ne différencie pas le thread principal des autres. Je ne connais pas de mécanisme pour le faire; tandis que certaines versions de l'exécution C vont toutes ExitProcess() à la fin du thread principal, dans toutes les versions récentes, le processus continue à s'exécuter jusqu'à ce que le dernier thread se termine.

La recommandation d'Interjay d'utiliser GetThreadTimes peut être la meilleure option. Si vous pouvez CreateProcess() le processus cible, le membre hThread du bloc PROCESS_INFORMATION contient le TID pour le thread principal. Bienvenue à toutes les idées des autres.

+0

Je me demande comment un logiciel comme OllyDbg découvre ce qu'est le "thread principal". Vous pouvez également joindre à des processus déjà en cours d'exécution avec elle. – Etan

+0

DebugActiveProcess() - http://msdn.microsoft.com/en-us/library/ms679295%28VS.85%29.aspx GetThreadContext() renvoie les registres pour le "contexte de thread actuel", mais aucune distinction de primaire thread je suis au courant. –

3

Pourquoi (si vous avez utilisé extern à) ne vous suffit de créer un programme mondial à l'échelle

HANDLE mainThread ; 
DWORD mainThreadId ; 

Sur la première ligne principale, (avant que les threads sont créés) faire

mainThread = GetCurrentThread() ; 
mainThreadId = GetCurrentThreadId() ; 

Vous pouvez utiliser any form of IPC pour partager l'ID ou la poignée avec le processus distant (n'ont pas vérifié le partage de la MANCHE fonctionne, mais il se doit!)

+0

Pourquoi dans main et pas simplement 'HANDLE mainThread = GetCurrentThread()'? – Liviu

+0

Aussi demandé ici: http://stackoverflow.com/questions/13287963/id-of-main-thread-in-c – Liviu

+1

Selon les docs de 'GetCurrentThread()', il renvoie un pseudo-handle, pas un handle , donc l'utiliser pour la comparaison ne fonctionnerait pas, je suppose. – Pol

6

obtenir l'ID de fil avec cette fonction:

/* CAUTION: ONLY x86 TESTED 
* get the thread id of the main thread of a target process 
* 
* params: 
*  DWORD dwPid process id of the target process 
* 
* return: 
*  Success  thread id 
*  Error  NULL 
*/ 
DWORD GetMainThreadId(DWORD dwPid) 
{ 
    LPVOID lpTid; 

    _asm 
    { 
     mov eax, fs:[18h] 
     add eax, 36 
     mov [lpTid], eax 
    } 

    HANDLE hProcess = OpenProcess(PROCESS_VM_READ, FALSE, dwPid); 
    if(hProcess == NULL) 
     return NULL; 

    DWORD dwTid; 
    if(ReadProcessMemory(hProcess, lpTid, &dwTid, sizeof(dwTid), NULL) == FALSE) 
    { 
     CloseHandle(hProcess); 
     return NULL; 
    } 

    CloseHandle(hProcess); 

    return dwTid; 
} 

simple ouvrir le fil pour obtenir la poignée:

/* 
* get a handle to the main thread of a target process 
* if successfull, the returned handle must be closed with CloseHandle() 
* 
* params: 
*  DWORD dwPid    process id of the target process 
*  DWORD dwDesiredAccess desired access rights to the thread 
* 
* return: 
*  Success  thread handle with desired access rights 
*  Error  NULL 
*/ 
HANDLE GetMainThreadHandle(DWORD dwPid, DWORD dwDesiredAccess) 
{ 
    DWORD dwTid = GetMainThreadId(dwPid); 
    if(dwTid == FALSE) 
     return NULL; 

    return OpenThread(dwDesiredAccess, FALSE, dwTid); 
} 
+2

Je ne crois pas que cela fonctionnera parfaitement dans différents environnements. Plus précisément, vous supposez que les adresses Tib sont toutes égales dans chaque processus sur toutes les machines et même l'appelant de GetMainThreadId() est le thread principal, n'est-ce pas? Vous devriez expliquer comment cela fonctionne car il a trop de choses suspectes à demander. – Laie

+0

C'est génial, mais j'essaie de rendre une fonction compatible avec 32 et 64 bits – Acidic

Questions connexes