请问您能帮我查找给定进程的主(唯一)线程ID吗?
任务背景: 正在运行的进程当前没有窗口,但有一个或多个线程。
要求:
仅在主线程中发出 WM_QUIT
。
不要:
使用 TerminateProcess
或在非主线程中发布 WM_QUIT
。
请问您能帮我查找给定进程的主(唯一)线程ID吗?
任务背景: 正在运行的进程当前没有窗口,但有一个或多个线程。
要求:
仅在主线程中发出 WM_QUIT
。
不要:
使用 TerminateProcess
或在非主线程中发布 WM_QUIT
。
获取主线程的线程ID更简单、更可靠的方法是让主线程使用::GetCurrentThreadId()
将自己的线程ID记录到共享全局变量中,可以在WinMain或者'main thread'的开头处完成:
MainThreadId_G = ::GetCurrentThreadId();
然后在您的其他线程中,您可以调用:::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);
#ifndef MAKEULONGLONG
#define MAKEULONGLONG(ldw, hdw) ((ULONGLONG(hdw) << 32) | ((ldw) & 0xFFFFFFFF))
#endif
#ifndef MAXULONGLONG
#define MAXULONGLONG ((ULONGLONG)~((ULONGLONG)0))
#endif
bool CloseProcessMainThread(DWORD dwProcID)
{
DWORD dwMainThreadID = 0;
ULONGLONG ullMinCreateTime = MAXULONGLONG;
HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
if (hThreadSnap != INVALID_HANDLE_VALUE) {
THREADENTRY32 th32;
th32.dwSize = sizeof(THREADENTRY32);
BOOL bOK = TRUE;
for (bOK = Thread32First(hThreadSnap, &th32); bOK;
bOK = Thread32Next(hThreadSnap, &th32)) {
if (th32.th32OwnerProcessID == dwProcID) {
HANDLE hThread = OpenThread(THREAD_QUERY_INFORMATION,
TRUE, th32.th32ThreadID);
if (hThread) {
FILETIME afTimes[4] = {0};
if (GetThreadTimes(hThread,
&afTimes[0], &afTimes[1], &afTimes[2], &afTimes[3])) {
ULONGLONG ullTest = MAKEULONGLONG(afTimes[0].dwLowDateTime,
afTimes[0].dwHighDateTime);
if (ullTest && ullTest < ullMinCreateTime) {
ullMinCreateTime = ullTest;
dwMainThreadID = th32.th32ThreadID; // let it be main... :)
}
}
CloseHandle(hThread);
}
}
}
#ifndef UNDER_CE
CloseHandle(hThreadSnap);
#else
CloseToolhelp32Snapshot(hThreadSnap);
#endif
}
if (dwMainThreadID) {
PostThreadMessage(dwMainThreadID, WM_QUIT, 0, 0); // close your eyes...
}
return (0 != dwMainThreadID);
}
我查看了MFC中的处理方式,看起来UI线程是在构造函数中确定的:
C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\appcore.cpp:
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
...
m_nThreadID = ::GetCurrentThreadId();
使用MFC的AfxGetApp()->m_nThreadID
方法,您可以找出UI线程的ID。
然而,这种方法在.dll文件不是从主线程加载时不起作用 - 即使是MFC的方法也无法正常工作 - AfxGetApp()->m_nThreadID
将返回与主线程不同的内容。
但通常情况下,您的.dll文件会从主线程加载,但不一定启用MFC。我建议采用以下方法:
class GetMainThread
{
public:
GetMainThread()
{
m_nThreadID = ::GetCurrentThreadId();
}
DWORD m_nThreadID;
}getMainThread;
DWORD getUIThread()
{
DWORD id = 0;
if( AfxGetApp() != NULL )
id = AfxGetApp()->m_nThreadID;
else
id = getMainThread.m_nThreadID;
return id;
} //getUIThread
在你的cpp文件开头使用这个,而不是在一个函数中:
DWORD mainThreadID = ::GetCurrentThreadId();
DWORD WINAPI GetProcessIdOfThreadId(_In_ DWORD ThreadId)
{
HANDLE Thread = OpenThread(THREAD_QUERY_LIMITED_INFORMATION, FALSE, ThreadId);
DWORD process_id = GetProcessIdOfThread(Thread);
CloseHandle(Thread);
return process_id;
}
您无法向特定线程发布消息。消息将被放入队列中,并仅从主线程处理。
如果您想关闭具有 UI 的 Windows 进程,请查看 使用 SendMessage 向另一个进程发送 WM_CLOSE。
PostThreadMessage
。实际上,如果 Win32 提供了一个 PostProcessMessage 并且你的假设是正确的(或者至少对于这个目的是有效的),那么这将会更容易。但不幸的是,事实并非如此... - Mordachai