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

Can you help me find the main (only) thread identifier of this identification process, please?

Task context: In the current process (at the moment) there are no windows, but (some) threads.

Required: Posting WM_QUIT only in the main thread.

Not wanted: Using TerminateProcess or publishing WM_QUIT in non-primary threads.

+6
source share
4 answers
 #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); } 
+6
source

A simpler and more reliable way to get the thread id of the main thread is to let the main thread write its own thread id using ::GetCurrentThreadId() into a global global variable, possibly in your WinMain or somewhere at the very beginning of your main thread:

 MainThreadId_G = ::GetCurrentThreadId(); 

then in your other threads you can call: ::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);

+4
source

You cannot post to a specific thread. Messages are queued and processed only from the main thread.

If you want to close the Windows process with the user interface, look using sendmessage to send wm_close to another process

+2
source

I checked how this is handled in MFC, and it looks like the UI thread is defined from the constructor:

 C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\appcore.cpp: CWinApp::CWinApp(LPCTSTR lpszAppName) { ... m_nThreadID = ::GetCurrentThreadId(); 

And using the MFC call AfxGetApp()->m_nThreadID , you can determine the thread identifier of the user interface.

However - this approach does not work if the .dll was not loaded from the main thread - then even the MFC approach will not work - AfxGetApp()->m_nThreadID will return something else than the main thread.

But usually your .dll is loaded from the main thread, but your .dll is not needed by mfc. I could recommend this approach:

 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 

If the .dll is loaded by the main user interface thread, you will get the correct thread identifier from the constructor call (GetMainThread class).

Remove AfxGetApp() calls if you don't need them (in my application I needed)

+1
source

All Articles