2009-12-28 5 views
10

Я создал дополнительный поток в небольшом тестовом приложении и хочу приостановить основной поток из этого дополнительного потока. Дополнительный поток создается через CreateRemoteThread из внешнего процесса.Получение дескриптора основного потока процесса

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

+0

Что ваша целевая платформа? –

+0

Это 32-разрядный процесс под окнами 7. Я использую Visual Studio 2008 и, следовательно, Visual C++. – Etan

+0

Вы хотите приостановить только «основную» нить или все? Что именно вы пытаетесь достичь? У него может быть другой способ сделать это ... – cedrou

ответ

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

Гарантируется, что «основной» поток процесса всегда будет первым в моментальном снимке? Кроме того, речь шла не о том, как определить основной поток; речь шла о том, как получить дескриптор, который этот ответ игнорирует. –

+5

Нет даже гарантии, что «основной» поток процесса все еще существует! Основной поток процесса, возможно, сделал «ExitThread». –

14

Я не думаю, что есть что-то, что отличает основной поток от других потоков после начала процесса. Однако вы можете enumerate all threads in the process и использовать GetThreadTimes, чтобы найти тему с самым ранним временем создания. Вызовите OpenThread, чтобы получить HANDLE из идентификатора потока.

2

Ряд полезных функций API этого типа находится под комплектом (конечно!) Tool Help. API CreateToolhelp32Snapshot() выполнит моментальный снимок выполняемых потоков для определенного процесса.

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

Полный пример кода here.

структура, которая возвращается не дифференцирует основную нить от других. Я не знаю механизма для этого; в то время как в некоторых версиях среды выполнения C все ExitProcess() в конце основного потока, во всех последних версиях процесс продолжает работать до тех пор, пока последний поток не выйдет.

Рекомендация Interjay по использованию GetThreadTimes может быть лучшей ставкой. Если вы можете CreateProcess() целевого процесса, член hThread блока PROCESS_INFORMATION содержит значок для основного потока. Приветствуйте любые идеи от других.

+0

Интересно, как программное обеспечение, такое как OllyDbg, выясняет, что такое «основной поток». Вы также можете подключиться к уже запущенным процессам. – Etan

+0

DebugActiveProcess() - http://msdn.microsoft.com/en-us/library/ms679295%28VS.85%29.aspx GetThreadContext() возвращает регистры для «текущего контекста потока», но никакого различия первичного поток, о котором я знаю. –

3

Почему вы не просто создать программу для всей глобальной (использование extern если вы должны)

HANDLE mainThread ; 
DWORD mainThreadId ; 

На первой линии основной (до того, как потоки создаются) делают

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

Вы можете использовать any form of IPC разделить идентификатор или РУЧКУ с удаленным процессом (не проверен обменом РУЧКА будет работать, но он должен!)

+0

Почему в основном, а не просто 'HANDLE mainThread = GetCurrentThread()'? – Liviu

+0

Также задан здесь: http://stackoverflow.com/questions/13287963/id-of-main-thread-in-c – Liviu

+1

Согласно документам 'GetCurrentThread()', он возвращает псевдо-дескриптор, а не дескриптор , поэтому использовать его для сравнения не получится. – Pol

6

Получить идентификатор потока с помощью этой функции:

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

Простой открыть нить, чтобы получить ручку:

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

Я не верю, что это будет отлично работать в разных средах. В частности, вы предполагаете, что адреса тиба одинаковы в каждом процессе на всех машинах, и даже вызывающий объект GetMainThreadId() является основным потоком, не так ли? Вы должны объяснить, как это работает, поскольку у него слишком много подозрительных вещей, чтобы спросить. – Laie

+0

Это потрясающе, но я пытаюсь сделать функцию, совместимую с 32 и 64 бит – Acidic