2009-12-28 14 views
10

Ho creato un thread aggiuntivo in alcune piccole applicazioni di test e desidero sospendere il thread principale da questo thread aggiuntivo. Il thread aggiuntivo viene creato tramite CreateRemoteThread da un processo esterno.Come gestire il thread principale del processo

Dato che SuspendThread ha bisogno di un HANDLE per il thread che deve essere sospeso, voglio sapere come ottenere questo HANDLE dal codice in esecuzione nel mio thread aggiuntivo.

+0

Qual è la piattaforma di destinazione? –

+0

È un processo a 32 bit in Windows 7. Uso Visual Studio 2008 e, quindi, Visual C++. – Etan

+0

Vuoi sospendere solo il thread "principale" o tutti? Cosa stai cercando di ottenere esattamente? Potrebbe avere un altro modo per farlo ... – cedrou

risposta

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

È garantito che il thread "principale" di un processo sarà sempre il primo di un'istantanea? Inoltre, la domanda non era su come identificare il thread principale; si trattava di come ottenere una maniglia, che questa risposta ignora. –

+5

Non c'è nemmeno la garanzia che il thread "principale" di un processo esista ancora! Il thread principale del processo potrebbe aver eseguito un 'ExitThread'. –

2

Un numero di funzioni API utili di questo tipo si trovano nella suite (ovviamente!) Tool Help. L'API CreateToolhelp32Snapshot() acquisirà un'istantanea dei thread in esecuzione per un processo specificato.

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

codice here.

struttura restituita non distingue thread primario dagli altri esempio completo. Non conosco un meccanismo per farlo; mentre alcune versioni del runtime C saranno tutte ExitProcess() alla fine del thread primario, in tutte le versioni recenti il ​​processo continua a essere eseguito fino all'uscita dell'ultimo thread.

La raccomandazione di Interjay di utilizzare GetThreadTimes potrebbe essere la soluzione migliore. Se è possibile eseguire il processo di destinazione CreateProcess(), il membro hThread del blocco PROCESS_INFORMATION contiene il tid per il thread primario. Accogli le idee degli altri.

+0

Mi chiedo come software come OllyDbg scopre quale sia il "filo conduttore". È inoltre possibile associare a processi già in esecuzione con esso. – Etan

+0

DebugActiveProcess() - http://msdn.microsoft.com/en-us/library/ms679295%28VS.85%29.aspx GetThreadContext() restituisce i registri per il "contesto thread corrente", ma nessuna distinzione di primaria filo di cui sono a conoscenza. –

3

Perché non basta creare un ampio programma globale (uso extern se si deve)

HANDLE mainThread ; 
DWORD mainThreadId ; 

Nella prima riga del principale (prima di creare qualsiasi thread) fare

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

è possibile utilizzare any form of IPC per condividere l'ID o la maniglia con il processo a distanza (non hanno verificato condividere la maniglia funzionerà, ma dovrebbe!)

+0

Perché main e non semplicemente 'HANDLE mainThread = GetCurrentThread()'? – Liviu

+0

Anche qui: http://stackoverflow.com/questions/13287963/id-of-main-thread-in-c – Liviu

+1

Secondo i documenti di 'GetCurrentThread()', restituisce uno pseudo-handle, non un handle quindi utilizzarlo per un confronto non funzionerebbe, presumo. – Pol

6

ottenere l'ID filo con questa funzione:

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

semplice aprire la discussione per ottenere la maniglia:

/* 
* 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

Non credo che funzionerà perfettamente su vari ambienti. In particolare, si presuppone che gli indirizzi Tib siano tutti uguali in ogni processo su tutte le macchine e anche il chiamante di GetMainThreadId() è il thread principale, giusto? Dovresti spiegare come funziona in quanto ha troppe cose sospette da chiedere. – Laie

+0

Questo è fantastico, ma sto cercando di rendere una funzione compatibile con 32 e 64 bit – Acidic