2009-12-28 27 views
10

He creado un hilo adicional en una pequeña aplicación de prueba y quiero suspender el hilo principal de este hilo adicional. El hilo adicional se crea a través de CreateRemoteThread desde un proceso externo.Manejando el hilo principal del proceso

Dado que SuspendThread necesita un HANDLE al hilo que se debe suspender, quiero saber cómo obtener este HANDLE del código que se ejecuta en el hilo adicional.

+0

¿Cuál es su plataforma de destino? –

+0

Es un proceso de 32 bits en Windows 7. Estoy usando Visual Studio 2008 y, por lo tanto, Visual C++. – Etan

+0

¿Desea suspender solo el hilo "principal" o todo? ¿Qué estás tratando de lograr exactamente? Podría tener otra forma de hacerlo ... – cedrou

Respuesta

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

¿Se garantiza que el hilo "principal" de un proceso siempre será el primero en una instantánea? Además, la pregunta no era sobre cómo identificar el hilo principal; se trataba de cómo obtener un mango, que esta respuesta ignora. –

+5

¡Ni siquiera hay garantía de que el hilo "principal" de un proceso aún exista! El hilo principal del proceso puede haber hecho un 'ExitThread'. –

2

Una serie de útiles funciones de API de este tipo se encuentran bajo (¡por supuesto!) Tool Help suite. La API CreateToolhelp32Snapshot() tomará una instantánea de los subprocesos en ejecución para un proceso específico.

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

ejemplo completo de código here.

La estructura devolver no diferenciar el hilo principal de las otras. No conozco un mecanismo para hacerlo; mientras que algunas versiones del tiempo de ejecución de C tendrán ExitProcess() al final del subproceso principal, en todas las versiones recientes, el proceso continúa ejecutándose hasta que finalice el último.

La recomendación de Interjay de utilizar GetThreadTimes puede ser la mejor opción. Si puede CreateProcess() el proceso de destino, el miembro hThread del bloque PROCESS_INFORMATION contiene el tid para el hilo primario. Bienvenido cualquier idea de los demás.

+0

Me pregunto cómo software como OllyDbg descubre cuál es el "hilo principal". También puede adjuntarlo a procesos que ya se están ejecutando. – Etan

+0

DebugActiveProcess() - http://msdn.microsoft.com/en-us/library/ms679295%28VS.85%29.aspx GetThreadContext() devuelve los registros para el "contexto de subproceso actual", pero no distingue entre primario hilo de lo que estoy enterado. –

3

¿Por qué no basta con crear un amplio programa mundial (uso extern si tiene que)

HANDLE mainThread ; 
DWORD mainThreadId ; 

En la primera línea del principal, (antes de crear hilos) hacer

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

puede utilizar any form of IPC compartir el ID o el mango con el proceso remoto (no han verificado compartir el MANGO funcionará pero debería!)

+0

¿Por qué en main y no simplemente 'HANDLE mainThread = GetCurrentThread()'? – Liviu

+0

También se pregunta aquí: http://stackoverflow.com/questions/13287963/id-of-main-thread-in-c – Liviu

+1

De acuerdo con los documentos de 'GetCurrentThread()', devuelve un pseudo-mango, no un controlador , entonces usarlo para comparar no funcionaría, supongo. – Pol

6

obtener el ID del hilo con esta función:

/* 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 abrir el hilo para obtener el identificador:

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

No creo que esto funcione perfectamente en varios entornos. Específicamente, usted está asumiendo que las direcciones Tib son todas iguales en cada proceso en todas las máquinas e incluso la persona que llama de GetMainThreadId() es el hilo principal, ¿verdad? Debería explicar cómo funciona ya que tiene demasiadas cosas sospechosas que preguntar. – Laie

+0

Esto es increíble, pero estoy tratando de hacer una función compatible con 32 y 64 bits – Acidic

Cuestiones relacionadas