アプリケーションの初期化シーケンスをもう一度走らせたい場合など、 アプリケーションが、自身を再起動させたいときがたまにあります。 それを実現する方法です。
手順は以下の通りです。
サンプルコードを載せておきます。
再起動を行う部分のコードは以下の通りです。
TCHAR strPath[MAX_PATH];
::GetModuleFileName(AfxGetInstanceHandle(), strPath, sizeof(strPath) / sizeof(TCHAR));
TCHAR strCurDir[MAX_PATH];
::GetCurrentDirectory(sizeof(strCurDir) / sizeof(TCHAR), strCurDir);
// 元プロセスのコマンドライン引数を継承する必要があるか検討して下さい。
DWORD dwProcessId = ::GetCurrentProcessId();
CString strCmdLine;
strCmdLine.Format("/waitterminate %u", dwProcessId);
::ShellExecute(NULL, NULL, strPath, strCmdLine, strCurDir, SW_SHOWNORMAL);
// アプリケーションを終了する。
AfxGetMainWnd()->SendMessage(WM_COMMAND, MAKEWPARAM(ID_APP_EXIT, 0), NULL);
CXxxApp::InitInstanceに以下のコードを追加します。
BOOL CXxxApp::InitInstance()
{
bool bWaitTerminate = false;
DWORD dwWaitProcessId;
for (int i = 1; i < __argc; ++i) {
if (!(__argv[i][0] == '/' || __argv[i][0] == '-')) {
continue;
}
if (_tcsicmp(&__argv[i][1], "waitterminate") == 0) {
if (++i >= __argc) {
continue;
}
dwWaitProcessId = static_cast(_ttoi(__argv[i]));
if (dwWaitProcessId != 0) {
bWaitTerminate = true;
}
}
}
if (bWaitTerminate) {
HANDLE hWaitProcess = ::OpenProcess(SYNCHRONIZE, FALSE, dwWaitProcessId);
if (hWaitProcess != NULL) {
// 10秒待っても前のプロセスが終了しない場合は、アプリケーションを終了します。
if (::WaitForSingleObject(hWaitProcess, 10 * 1000) == WAIT_TIMEOUT) {
return FALSE;
}
}
}
// CXxxApp::InitInstanceの残りの処理を行う。
}
アイデアそのものはMFCに依存していないので、
ちょっと変更すればMFCを使わなくても実現できると思います。
投稿者 MASATO : 2004年05月09日 22:00
| トラックバック
Weblogに移行してからの初コメントどうもトありがとうございます。
これからもよろしくお願いします。
Weblog移行により簡単にコメントが付けられるようになりましたのでどんどん突っ込んじゃって下さい。