Получение дескриптора основного потока процесса
Я создал дополнительный поток в небольшом тестовом приложении и хочу приостановить основной поток из этого дополнительного потока. Дополнительный поток создается через CreateRemoteThread
из внешнего процесса.
Так как SuspendThread
нуждается в HANDLE
для потока, который должен быть приостановлен, я хочу знать, как получить этот HANDLE
из кода, запущенного в моем дополнительном потоке.
Ответы
Ответ 1
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;
}
Ответ 2
Я не думаю, что есть что-то, что отличает основной поток от других потоков после начала процесса. Однако вы можете перечислить все потоки процесса и использовать GetThreadTimes найти поток с самым ранним временем создания. Вызовите OpenThread, чтобы получить HANDLE
из идентификатора потока.
Ответ 3
Получить идентификатор потока с помощью этой функции:
/* 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);
}
Ответ 4
Почему бы вам просто не создать глобальную программу (используйте extern, если вам нужно)
HANDLE mainThread ;
DWORD mainThreadId ;
В первой строке main (перед созданием любых потоков) выполните
mainThread = GetCurrentThread() ;
mainThreadId = GetCurrentThreadId() ;
Вы можете использовать любую форму IPC для обмена либо идентификатором, либо РУЧКОЙ с удаленным процессом (еще не подтвердили, что совместное использование HANDLE будет работа, но он должен!)
Ответ 5
Несколько полезных функций API этого типа находятся под (конечно!) Tool Help. CreateToolhelp32Snapshot()
API сделает снимок текущих потоков для определенного процесса.
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( FALSE );
Полный пример кода здесь.
Возвращенная структура не отличает основной поток от других. Я не знаю механизма для этого; в то время как в некоторых версиях среды выполнения C будет все ExitProcess() в конце основного потока, во всех последних версиях процесс продолжает работать до тех пор, пока последний поток не выйдет.
Рекомендация Interjay использовать GetThreadTimes может быть лучшим выбором. Если вы можете CreateProcess()
целевой процесс, член hThread PROCESS_INFORMATION
содержит tid для основного потока. Приветствуйте любые идеи от других.