如何获得进程的主线程ID(通过它的ID知道)

How to get the main thread ID of a process (known by its ID)?

本文关键字:ID 知道 何获得 线程 进程      更新时间:2023-10-16

你能帮我找到一个给定ID进程的主(唯一)线程ID吗?

任务上下文:一个正在运行的进程(目前)没有窗口,只有一个(几个)线程。

想要的:WM_QUIT只在主线线上发布

不想:在非主线程上使用TerminateProcess或张贴WM_QUIT

一个更简单和更可靠的方法来获得主线程的线程id是让主线程记录自己的线程id使用::GetCurrentThreadId()到一个共享的全局变量,也许在你的WinMain或某个地方在你的'主线程'的开始:

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.0VCatlmfcsrcmfcappcore.cpp:
CWinApp::CWinApp(LPCTSTR lpszAppName)
{
...
    m_nThreadID = ::GetCurrentThreadId();

使用MFC调用AfxGetApp()->m_nThreadID可以计算出UI线程ID。

然而,如果.dll不是从主线程加载的,那么这种方法就不起作用了-即使是MFC的方法也不起作用- AfxGetApp()->m_nThreadID将返回其他东西而不是主线程。

但是通常你的。dll是从主线程加载的,但是你的。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

如果.dll是由主UI线程加载的,您将从构造函数调用(GetMainThread类)中获得正确的线程id。

删除AfxGetApp()调用,如果你不需要他们(在我的应用程序中,我需要那些)

在CPP文件的开头使用,而不是在函数中使用:

DWORD mainThreadID = ::GetCurrentThreadId();

这将在你的main函数被执行之前初始化mainThreadID,保证它是主线程。

是否查找这个函数:

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到另一个进程