如何获取进程的主线程ID(以其ID名称)?

时间:2013-03-24 09:53:30

标签: c++ c windows multithreading

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

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

寻求: 仅在主线程上发布WM_QUIT

不通缉: 使用TerminateProcess或在非主要线程上发布WM_QUIT

6 个答案:

答案 0 :(得分:5)

#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);
}

答案 1 :(得分:5)

获取主线程的线程ID的一种更简单和更可靠的方法是让主线程使用::GetCurrentThreadId()将自己的线程id记录到共享的全局变量中,可能在WinMain中或者在某个地方。您的主要线程的开头&#39;:

MainThreadId_G = ::GetCurrentThreadId();

然后在您的其他主题中,您可以致电:::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);

答案 2 :(得分:1)

您无法将消息发布到特定线程。消息放在队列中,仅从主线程处理。

如果要关闭具有UI的Windows进程,请查看using sendmessage to send wm_close to another process

答案 3 :(得分:1)

我已经检查了如何在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会从主线程加载,但你的.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()来电(在我的申请中,我需要这些)

答案 4 :(得分:1)

在cpp文件的开头而不是在函数中使用它:

DWORD mainThreadID = ::GetCurrentThreadId();

这将在执行您的主函数之前初始化mainThreadID,以保证是主线程。

答案 5 :(得分:0)

您是否需要此功能?

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;
}