2013-03-24 24 views
6

あなたはIDで指定されたプロセスのメイン(唯一の)スレッドIDを見つけるのを手伝ってもらえますか?プロセスのメインスレッドID(IDでわかる)を取得するにはどうすればよいですか?

タスクコンテキスト: 実行中のプロセスには(現時点では)ウィンドウはなく(一部の)スレッドがあります。

募集: 投稿はWM_QUITメインスレッドのみです。

不要: TerminateProcessを使用するか、プライマリ以外のスレッドでWM_QUITを使用してください。

答えて

6
#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

いいね、ありがとう! –

+6

このコードは、コードが何をし、どのように機能するかについての説明が含まれていれば、この回答になるでしょう。特に、そのプロセスに複数のスレッドがある場合、どの「メイン」スレッドが特定のプロセスのものであるかをどのように判断していますか?それはあなたがスレッドの作成時間に基づいているように私に見えます。これは必ずしも信頼できる発見的手法ではありません。このアプローチの長所と短所を慎重に考慮できる場所を指摘することが重要です。 * only *コードを含む回答は答えではありません。 –

2

特定のスレッドにメッセージを送信することはできません。メッセージはキューに入れられ、メインスレッドのみから処理されます。

あなたはUIを持つWindowsプロセスを終了する場合、using sendmessage to send wm_close to another process

+0

は私が有用であるとあなたの答えをマークします、お返事をいただき、ありがとうございます。 –

+3

実際には、複数のメッセージキューがあり、それぞれが異なるスレッドに関連付けられています。存在する場合は、PostThreadMessageを使用して特定のスレッドにメッセージを送信できます。 –

+0

@ハリー:それは知っているのは面白い!複数のキューが存在する現実的なユースケースは何ですか? – alex

4

を見てみましょうメインスレッドのスレッドIDを取得するには非常に簡単で、より確実な方法は、メインスレッドがを記録できるようにすることです

MainThreadId_G = ::GetCurrentThreadId(); 

が、あなたの他のスレッドでは、あなたが呼び出すことができます:あなたのWinMainにまたはどこかにあなたの「メインスレッド」の先頭に、おそらく、共有グローバル変数に ::GetCurrentThreadId()を使用して独自のスレッドID ::PostThreadMessage(MainThreadId_G, WM_QUIT, returncode, 0);

+0

私は間違いなくこの答えを好む。簡潔で、完全な答えと良い説明を提供します。もちろん、グローバル変数を使用する代わりに、作成時にメインスレッドIDをパラメータとしてワーカースレッドに渡すことは可能です。 –

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(); 

そして、あなたはUIスレッドIDを把握することができますMFC呼び出しAfxGetApp()->m_nThreadIDを使用。

しかし、.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()呼び出しを取り外します(私のアプリケーションでは、私はそれらを必要な)