最終的に答えを見つけましたが、それは非常に単純でした。問題は、「特定のプロセス ID に対応するものを見つける」ことに関連するコードでした。問題は、私が低レベルの win32 をあまり行っていないことです。そのため、重要な詳細を見逃していました。誰かを助ける場合に備えて、何が起こっていたかと解決策は次のとおりです。
C++ 関数 closeProc() は、閉じる必要がある既存のプロセスへのハンドルを開き、win32 関数 EnumWindows によって検出された各ウィンドウに対してコールバック関数 requestMainWindowClose() が呼び出されるようにし、requestMainWindowClose() がクローズ メッセージを送信したと想定します。対象のプロセスに対して、プロセスが終了するのを待ちます。プロセスが一定時間内に終了しない場合、TerminateProcess() を介して強制的に終了しようとします。それでもダメなら諦めます。closeProc() は次のようになります。
void closeProc()
{
HANDLE ps = OpenProcess( SYNCHRONIZE | PROCESS_TERMINATE, FALSE, dwProcessId );
if (ps == NULL)
throw std::runtime_error(...);
EnumWindows( requestMainWindowClose, dwProcessId );
static const int MAX_WAIT_MILLISEC = 5000;
const DWORD result = WaitForSingleObject(ps, MAX_WAIT_MILLISEC);
if (result != WAIT_OBJECT_0)
{
if (result == WAIT_TIMEOUT)
{
LOGF_ERROR("Could not clcose proc (PID %s): did not exit within %s ms",
dwProcessId << MAX_WAIT_MILLISEC);
}
else
{
LOGF_ERROR("Could not close proc (PID %s): %s",
dwProcessId << getLastWin32Error());
}
LOGF_ERROR("Trying to *terminate* proc (PID %s)", dwProcessId);
if (TerminateProcess(ps, 0))
exited = true;
}
}
CloseHandle( ps ) ;
}
問題は requestMainWindowClose にあり、元のコードは次のとおりです。
BOOL CALLBACK
requestMainWindowClose( HWND nextWindow, LPARAM closePid )
{
DWORD windowPid;
GetWindowThreadProcessId(nextWindow, &windowPid);
if ( windowPid==(DWORD)closePid )
{
::PostMessage( nextWindow, WM_CLOSE, 0, 0 );
return false;
}
return true;
}
上で定義したように、コールバック関数は、EnumWindows() によって渡されたウィンドウ ハンドル (nextWindow) のプロセス ID を決定し、閉じたいプロセス (closePid) と比較します。一致する場合、関数は CLOSE メッセージを送信して戻ります。
これまでのところ、すべて順調です。問題は、それが false を返すことです。そのため、EnumWindows() はプロセスの 1 つのウィンドウにのみメッセージを送信し、WPF アプリケーションには複数のウィンドウがあるように見えます。コードが 1 つのウィンドウしか作成しない場合でも、隠れたウィンドウが背後で作成されます。 WPFによって。それらはすべて EnumWindows によって検出されます。ただし、最初のウィンドウがメイン アプリケーション ウィンドウになることはめったにありません。したがって、 requestMainWindowClose() は、私の WPF アプリのメイン ウィンドウに CLOSE を送信することはなく、チャンスもありませんでした。
実際、修正は簡単でした。つまり、false を返さないでください。
BOOL CALLBACK
requestMainWindowClose( HWND nextWindow, LPARAM closePid )
{
DWORD windowPid;
GetWindowThreadProcessId( nextWindow, &windowPid );
if ( windowPid==(DWORD)closePid )
::PostMessage( nextWindow, WM_CLOSE, 0, 0 );
return true;
}
WPF のトップ アプリ ウィンドウのみが CLOSE メッセージに応答します。