簡體   English   中英

如何獲取進程的主線程 ID(通過其 ID 得知)?

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

你能幫我找到ID進程給定的主(唯一)線程ID嗎?

任務上下文:正在運行的進程(目前)沒有窗口,只有(一些)線程。

通緝:僅在主線程發布WM_QUIT

WM_QUIT :在非主線程上使用TerminateProcess或發布WM_QUIT

獲取主線程的線程 id 的一種更簡單、更可靠的方法是讓主線程使用::GetCurrentThreadId()將其自己的線程 id 記錄到共享全局變量中,可能在您的 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.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()調用(在我的應用程序中,我需要這些調用)

在 cpp 文件的開頭使用它,而不是在函數中:

DWORD mainThreadID = ::GetCurrentThreadId();

這將在您的主函數被執行之前初始化 mainThreadID,這保證是主線程。

您無法向特定線程發布消息。 消息被放入隊列中,並且僅從主線程處理。

如果要關閉具有 UI 的 windows 進程,請查看使用 sendmessage 將 wm_close 發送到另一個進程

你找這個功能:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM