• ベストアンサー

スレッド一覧の取得

こんにちわ。 VC6.0でWindowsNT4.0上で動作しているプロセス一覧及びスレッド 一覧を取得するツールを作成したいのですが、アドバイス下さい。 プロセス一覧に関しては、EnumProcessesを使用すればいいのかな? とめぼしはついたのですが、スレッド一覧の取得で壁に当たって います。 NT5.0以降であればCreateToolhelp32Snapshotなんかを使用して いけそうな感じもするのですが。 よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
noname#50176
noname#50176
回答No.3

実行中スレッド監視という処理概念で定義しますね。 1.SetWindowsHookEx()で、ForegroundIdleProc を渡す   つまり、システム上の全スレッドを監視します。 2.任意スレッドが実行されたらフックプロシージャが   呼び出されるのでここで、GetCurrentThreadId() 関数を   使います。   プロシージャからチェインする前に共有変数 <例>(DWORD th[65535]と定義)にスレッドIDをストア。 <例> for (int i=0;i<=インデックス;i++) if (th[i]==スレッドID) break; if (インデックス^i-1) th[インデックス++]=スレッドID 3.2の処理をTSR処理(常駐)させます。 4.メインアプリケーションでは共有変数を参照してIDを列挙します。 複雑で申し訳ないのですが一例としてどうでしょうか・・?

その他の回答 (3)

noname#50176
noname#50176
回答No.4

別スレッドが属するウインドウがアクティブにならない限り 自己スレッドのままになりますね・・・。 ブロードキャストでアクティブにすることもできますが、 処理がグズグスになるためフックは避けたほうがよさそうです。 スレッドIDを引数として取るAPI関数などでエラー(無効ID) 検出を使って0からスレッド最大個数整数値のループから拾う こともできるかもしれませんが・・。 あとはキー名はわかりませんが、レジストリ参照とか・・。 (結局参考にならず、すみません・・・)

noname#61827
質問者

お礼

ありがとうございました。 完全に満足するものは作成できませんでしたが、それなりのものは作成することが出来ました。何より、いろいろとフック関係の勉強になりました。

noname#50176
noname#50176
回答No.2

#1です。 "pEnd"変数は無視してください、未定義ゴミ変数です。

noname#61827
質問者

お礼

度々のフォローありがとうございます。 再度、質問させてください。 SetWindowsHookExなどをいろいろと調べて、私が望んでいる仕様に するには、システムフックにする必要があること。そうするには DLL化する必要があることなどは分かりました。 で、自分なりにコーディングしてみて、デバッカで確認しました。 SetWindowsHookExで指定したプロシージャが頻繁に呼ばれている ようですが、GetCurrentThreadIdの値が毎回同じになります。 ちなみに、このIdはDLL関数を呼び出す、メイン側のスレッドIdと 同じことも確認しました。 このような現象に関してなにか知識をお持ちでないでしょうか? 参考までにソースです ///// Cppファイル ///// #include "MyHooker.h" int WINAPI DllMain(HINSTANCE hInstance , DWORD dwReason , PVOID pvReserved) { ghDllInst = hInstance; memset(gdwThreadIds, NULL, MAXWORD); return(TRUE); } BOOL Hook() {   ghHook = SetWindowsHookEx(WH_FOREGROUNDIDLE, (HOOKPROC)Procedure, ghDllInst, 0);   if(ghHook) return(TRUE);   return(FALSE); } BOOL UnHook() {   if(ghHook) UnhookWindowsHookEx(ghHook);   ghHook = NULL;   return(TRUE); } LRESULT CALLBACK Procedure(int nCode, WPARAM wParam, LPARAM lParam) {   if(nCode < 0) return(CallNextHookEx(ghHook, nCode, wParam, lParam));   DWORD dwThreadId = GetCurrentThreadId();   for(int i = 0; i < MAXWORD; i++) {     if(gdwThreadIds[i] == dwThreadId) break;     if(gdwThreadIds[i] == NULL) {       gdwThreadIds[i] = dwThreadId;       break;     }   }   return CallNextHookEx(ghHook, nCode, wParam, lParam); } ///// ヘッダーファイル ///// #define DLL_EXPORT __declspec (dllexport) #include "windows.h" #pragma data_seg(".ShareData") HHOOK ghHook = NULL; #pragma data_seg() HINSTANCE ghDllInst = NULL; DLL_EXPORT BOOL Hook(); DLL_EXPORT BOOL UnHook(); DLL_EXPORT LRESULT CALLBACK Procedure(int nCode, WPARAM wParam, LPARAM lParam); ///// Defファイル ///// LIBRARY SECTIONS   .ShareData READ WRITE SHARED

noname#50176
noname#50176
回答No.1

<定義> typedef BOOL (WINAPI *_EnumProcesses)(DWORD*,DWORD,DWORD*); typedef BOOL (WINAPI *_EnumProcessModules)(HANDLE,HMODULE*,DWORD,LPDWORD); typedef DWORD (WINAPI *_GetModuleBaseName)(HANDLE,HMODULE,LPTSTR,DWORD); _EnumProcesses EnumProcesses; _EnumProcessModules EnumProcessModules; _GetModuleBaseName GetModuleBaseName; <処理> HMODULE hDll,hModule[1]; HANDLE hToken, hProcess; TOKEN_PRIVILEGES tp; LUID luid; CHAR pBuf[256]; DWORD pID[255],pNum=0,pNum2=0,i; OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken); LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&luid); tp.PrivilegeCount=1; tp.Privileges[0].Luid=luid; tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED; AdjustTokenPrivileges(hToken,FALSE,&tp,sizeof(TOKEN_PRIVILEGES),NULL,NULL); hDll=LoadLibrary("psapi.dll"); EnumProcesses=(_EnumProcesses)GetProcAddress(hDll,"EnumProcesses"); EnumProcessModules=(_EnumProcessModules)GetProcAddress(hDll,"EnumProcessModules"); GetModuleBaseName=(_GetModuleBaseName)GetProcAddress(hDll,"GetModuleBaseNameA"); i=(EnumProcesses)(pID,sizeof(pID),&pNum); pNum/=sizeof(DWORD); for (i=0,pEnd=true;i<pNum;i++) { hProcess=OpenProcess(PROCESS_ALL_ACCESS,0,pID[i]); if (!hProcess) {CloseHandle(hProcess);continue;} (EnumProcessModules)(hProcess,hModule,sizeof(hModule),&pNum2); (GetModuleBaseName)(hProcess,hModule[0],pBuf,sizeof(pBuf)); // pBuf=プロセス名 CloseHandle(hProcess); } CloseHandle(hToken); FreeLibrary(hDll); がシステムプロセス(WinLogon.exe など)も列挙する一例ですが、 スレッド名はEnumWindowsを使います。 そもそもスレッドは名目実体がないため、列挙トップウインドウの ハンドルからタイトルとスレッドID(GetWindowThreadProcessId) を取得して、列挙終了後に昇順に並べたスレッドIDごとに ID一致するタイトル名をツリー階層表示するのが良いと思いますよ。 参考にしてみてください。

noname#61827
質問者

お礼

ご回答ありがとうございます。 おっしゃっている意味は大体理解できました。 ただ、GetWindowThreadProcessIdだと、トップレベルウィンドウを 作成したスレッドのIDを取得する感じですよね。 例えば、マルチスレッドのアプリケーションなどの場合は複数の スレッドが生成されていると思うのですが、その複数のスレッド すべてのIDを取得するのは難しいのですかね? 質問ばかりで申し訳ありません。

関連するQ&A