我在一些小的测试应用程序中创建了一个附加线程,并且想要暂挂这个附加线程的主线程。附加线程通过CreateRemoteThread
从外部进程创建。获取进程主线程的句柄
由于SuspendThread
需要一个HANDLE
到应该被挂起的线程,我想知道如何从运行在我的附加线程中的代码获得这个HANDLE
。
我在一些小的测试应用程序中创建了一个附加线程,并且想要暂挂这个附加线程的主线程。附加线程通过CreateRemoteThread
从外部进程创建。获取进程主线程的句柄
由于SuspendThread
需要一个HANDLE
到应该被挂起的线程,我想知道如何从运行在我的附加线程中的代码获得这个HANDLE
。
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;
}
是否保证进程的“主”线程始终是快照中的第一个线程?另外,问题不在于如何确定主线程;这是关于如何得到一个句柄,这个答案忽略。 – 2010-07-14 14:00:07
甚至没有保证进程的“主”线程仍然存在!该进程的主线程可能已经完成了'ExitThread'。 – 2011-11-09 00:20:14
我不认为有什么区别主线程和其他线程,一旦进程已经开始。但是,您可以enumerate all threads in the process,并使用GetThreadTimes查找具有最早创建时间的线程。致电OpenThread从线程ID获取HANDLE
。
这种类型的许多有用的API函数都在(当然是!)Tool Help套件下。 CreateToolhelp32Snapshot()
API将为指定的进程拍摄正在运行的线程的快照。
// 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()
目标进程,则PROCESS_INFORMATION
块的hThread成员包含主线程的tid。欢迎来自他人的任何想法。
我想知道像OllyDbg这样的软件如何找出“主线程”是什么。您也可以使用它附加到已经运行的进程。 – Etan 2009-12-28 16:38:58
DebugActiveProcess() - http://msdn.microsoft.com/en-us/library/ms679295%28VS.85%29.aspx GetThreadContext()返回“当前线程上下文”的寄存器,但不区分主我知道的线程。 – 2009-12-28 21:20:30
你为什么不只是创建一个计划范围的全球性(使用extern如果你有)
HANDLE mainThread ;
DWORD mainThreadId ;
在主的第一行,(在创建任何线程之前)做
mainThread = GetCurrentThread() ;
mainThreadId = GetCurrentThreadId() ;
您可以使用any form of IPC共享所述1D或与远程进程的句柄(未验证共享手柄会工作,但它应该!)
获取线程ID使用此项功能:
/* 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);
}
什么是你的目标平台? – 2009-12-28 14:03:17
这是Windows 7下的一个32位程序。我使用Visual Studio 2008,因此使用Visual C++。 – Etan 2009-12-28 14:09:00
你只想暂停“主”线程还是全部?你究竟想达到什么目的?它可能有另一种方式来做到这一点...... – cedrou 2009-12-28 14:14:01