ページ 11

DLLで呼び出し元のウィンドウハンドルを取得したい

Posted: 2010年6月20日(日) 00:21
by MUN
VC++2008にてアンマネージドのDLLを作成しているのですが、
行き詰ってしまったので御教授下さい。

DLL側で呼び出しもとのウィンドウハンドル(HWND)を取得したいのですが、
取得で出来ずに悩んでいます。
事情により、引数にウィンドウハンドルを貰う事ができないため、どうして良いか悩んでます。
というのもDllMainで取得する必要があるからです。
呼び出し元がウィンドウであり、プロセスアタッチ時に呼び出し元のウィンドウハンドルを取得したいと考えて射ます。 画像

Re:DLLで呼び出し元のウィンドウハンドルを取得したい

Posted: 2010年6月20日(日) 06:19
by へろりくしょん
ずばっと出来るスマートな方法はないはずです。

EnumWindows()とか、FindWindow()とかでウィンドウハンドルを列挙したあと、GetWindowThreadProcessID()あたりで、呼び出し側のプロセスID等を比較して探し出すしかないかと思われます。

どういう使われ方をするDLLなのか解りませんが、初期化関数でも定義して、その関数に引数として与え、記憶させておくのが一番スマートな気がします。

Re:DLLで呼び出し元のウィンドウハンドルを取得したい

Posted: 2010年6月20日(日) 08:36
by シエル
呼び出し側からウィンドウハンドルをファイルに特定の名前で書き出し、
DLL側でそれを呼んで取得するしか思いつきません。

Re:DLLで呼び出し元のウィンドウハンドルを取得したい

Posted: 2010年6月20日(日) 22:49
by MUN
返信有難う御座います。

> EnumWindows()とか、FindWindow()とかでウィンドウハンドルを列挙したあと、GetWindowThreadProcessID()あたりで、呼び出し側のプロセスID等を比較して探し出すしかないかと思われます。
何も書かないですみませんでした。
私もそう思って色々試してみました。
下記コードであればEnumProcessModulesまでは成功しますが、モジュール名が取得で失敗する様です。
取得したいウィンドウハンドルのアプリは既に出来上がったものでして、何も出来ないのが現状です。

何をしたいのかともうしますと、呼び出し元のタイトルバーのTEXTを取得したいのです。
しかしながら、複数インストールが可能で、複数起動するWindowアプリケーションのため、
このDLLが呼ばれた際に呼び出し元のアプリケーションが分かればと思ったのです。

下記コードでやりたい事は、呼び出し元のEXEのPATHとDLLのPATHを比較して特定しようと考えているものです。
GetModuleFileNameExで失敗するため、EXEのPATHと比較できずにいます。
ご教授御願いします。

char g_mName[MAX_PATH];
BOOL CALLBACK EnumWindowsProc(HWND hWnd, LPARAM lParam)
{
//クラス名取得
char name[1024];
::GetClassNameA(hWnd, name, sizeof(name));
if(::strcmp("アプリケーションクラス名", name) != 0)
{
return TRUE;
}

//プロセスID取得
DWORD pid = 0;
::GetWindowThreadProcessId(hWnd, &pid);
if(pid == 0)
{
return TRUE;
}

//プロセスハンドル取得
HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
if(hProcess == 0)
{
return TRUE;
}

//プロセス内のモジュールのハンドルリストを取得
DWORD size = 0;
HMODULE hModule[1024];
if(::EnumProcessModules(hProcess, hModule, sizeof(hModule), &size) == 0)
{
return TRUE;
}

//モジュール名取得
int len = 0;
char path[MAX_PATH];
if(::GetModuleFileNameEx(hProcess, hModule[0], path, len) == 0)
{
::MessageBoxA(NULL, "GetModuleFileNameEx NG", "", MB_OK);
return TRUE;
}
::MessageBoxA(NULL, path, "", MB_OK);

//モジュール(又はEXEのPATH)とDLLのPAYHを比較する。
return TRUE;
}


BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
switch(ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
::GetModuleFileName(hModule, g_mName, MAX_PATH);
::EnumWindows(EnumWindowsProc, NULL);
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
case DLL_PROCESS_DETACH:
break;
}

return(TRUE);
} 画像

Re:DLLで呼び出し元のウィンドウハンドルを取得したい

Posted: 2010年6月20日(日) 23:30
by MUN
GetModuleFileNameExで最後引数で0を指定していたのが原因でした^^;

有難う御座いました。

Re:DLLで呼び出し元のウィンドウハンドルを取得したい

Posted: 2010年6月21日(月) 00:05
by YuO
解決となっていますが,なんだか大回りしているようなので……。


EnumWindows + GetWindowThreadProcessId + GetCurrentProcessId
で終わる話ではありませんか。

> //プロセスハンドル取得
から
> //モジュール(又はEXEのPATH)とDLLのPAYHを比較する。
までが全て削除し,
pidと::GetCurrentProcessId()が等しいものを探せば良くなります。

MSDN: GetCurrentProcessId Function (Windows)
http://msdn.microsoft.com/en-us/library/ms683180.aspx

Re:DLLで呼び出し元のウィンドウハンドルを取得したい

Posted: 2010年6月21日(月) 16:22
by MUN
YuOさん>

返信ありがとうございます。

ご指摘の通り思った事が出来ました!
有難う御座いました。