32ビットフックDLLファイルをインストールし、親プログラム(64ビットプログラム)が終了するまで待つことだけを目的としたウィンドウレスアプリケーションがあります。64ビットプログラムはC#で記述されており、ウィンドウレスアプリケーションはC++で記述されています。私はもともと、プログラムを開いたままにするこのGetMessageループを持っていました:
while(GetMessage(&msg, NULL, 0, 0) > 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
C#でProcess.Killメソッドを使用してC ++アプリケーションを閉じていましたが、それではC++アプリケーションを完全に閉じることができないことがわかりました。また、C#アプリケーションがクラッシュした場合、C++アプリケーションは永久に開いたままになります。次のループを使用して、C ++アプリケーションでC#アプリケーションがまだ実行されているかどうかを確認しました。
while(true)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
Sleep(1000);
}
何らかの理由で、睡眠は問題を引き起こします。DLLファイルによってインストールされるフックはWH_CBTとWH_KEYBOARDです。このループでC++アプリケーションを実行しているときにキーを押すと、キーが使い果たされてしまいます。スリープを削除すると正常に動作しますが、予想どおり、100%CPUを使用します。これは望ましくありません。メッセージループを完全に削除し、代わりにisMainProgramRunningがfalseを返したときに終了するスレッドで無限のタイムアウトを持つWaitForSingleObjectを使用してみました。これは基本的にコンピュータ全体をロックします。
GetMessageは、私が見た限りでは戻ってこなかったが、メインスレッドを無期限に中断したためにこれらの問題が発生しなかった理由はよくわかりませんが、WaitForSingleObjectをクリックすると、すべてのアプリケーションがフリーズします。C#アプリケーションが閉じるまでC ++アプリケーションを開いたままにするにはどうすればよいですか?
編集:
メッセージポンプでのスリープが悪いことが指摘されたので、これを聞いてみましょう:メッセージ待機のタイムアウトを指定する方法はありますか?プログラムはメッセージを無期限に待機するのではなく、約250ミリ秒待って、タイムアウトし、isMainProgramRunningメソッドを実行してから、もう少し待ちますか?
Edit2:
私はMsgWaitForMultipleObjectsを使用してみましたが、Leoが提案した方法とは多少異なります。これは私が使用したループです:
while(MsgWaitForMultipleObjects (0, NULL, true, 250, QS_ALLPOSTMESSAGE) != WAIT_FAILED)
{
if(PeekMessage(&msg, NULL, 0, 0, true))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if(!isMainProgramRunning())
break;
}
繰り返しますが、私は睡眠に関して同じ問題を抱えていました。また、メインスレッドを一時停止して、他のスレッドに再開させてみました。同じ問題。これらの問題を引き起こさずに待機できるようにするGetMessageの機能は何ですか?これは別の投稿の対象になるかもしれませんが、フックをインストールしているC ++アプリケーションがスリープまたは一時停止すると、フック内のすべての処理も一時停止しているように見えるのはなぜですか?
Edit3:
フックをインストールするためにC++アプリケーションが呼び出すDLLメソッドは次のとおりです。
extern "C" __declspec(dllexport) void install()
{
cbtHook = SetWindowsHookEx(WH_CBT, hookWindowEvents, hinst, NULL);
if(cbtHook == NULL)
MessageBox(NULL, "Unable to install CBT hook", "Error!", MB_OK);
keyHook = SetWindowsHookEx(WH_KEYBOARD, LowLevelKeyboardProc, hinst, NULL);
if(keyHook == NULL)
MessageBox(NULL, "Unable to install key hook", "Error!", MB_OK);
}