我在一些小的測試應用程序中創建了一個附加線程,並且想要暫掛這個附加線程的主線程。附加線程通過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