多重起動をOnInitDialogで行うには?


Ris  2008-03-11 07:43:19  No: 67808  IP: 192.*.*.*

お世話になっております、Risです。
VC++6.0、MFC、ダイアログベースで勉強しています。
宜しくお願いします。

アプリケーションの多重起動を防止したく、
以下のような手順を踏んだのですが、メモリーリークしてしまいます。
自分なりに試行錯誤したのですが修正することが出来ませんでした。


まずダイアログベースで、test というアプリケーションを作成します。
testDlg.cpp の CTestDlg::OnInitDialog()  内で

::CreateMutex(NULL, TRUE, "MUTEX_NAME");

if (::GetLastError() == ERROR_ALREADY_EXISTS) {

    HWND hWnd = this->GetSafeHwnd();

    if (hWnd) {

        TCHAR className[32];
        GetClassName(hWnd, className, sizeof(className));

        CWnd* cWndTarget = this->FindWindow(className, "APP_TITLE");

        throw cWndTarget;
    }

    throw NULL;
}

this->SetWindowText("APP_TITLE");

return TRUE;

そして、test.cpp の  CTestApp::InitInstance()  内で、

try {

    dlg.DoModal();

} catch (CWnd*& cWndTarget) {

    if (cWndTarget) {
        if (cWndTarget->IsIconic()) {
            cWndTarget->ShowWindow(SW_RESTORE);
        } else {
            cWndTarget->SetForegroundWindow();
        }
    }

//  AfxGetMainWnd()->PostMessage(WM_CLOSE);
    AfxGetMainWnd()->DestroyWindow();
}

としました。


PostMessageからDestroyWindowに変えてあるのは、

calling DestroyWindow in CDialog::~CDialog --
OnDestroy or PostNcDestroy in derived class will not be called.

というメッセージが出たのでMSDNで調べ、修正したからです。
(ここから間違っているかも知れません)


それと、catch (CWnd*& cWndTarget)  として参照を受け取っているのも、
参照を使わないとメモリリークするようなことが個人HPに書いてあったので
こうなっております。


このメモリーリークを回避するにはどうしたらよいのでしょうか?
どうぞ宜しくお願いします。

編集 削除
みい  2008-03-11 09:40:21  No: 67809  IP: 192.*.*.*

CTestDlg::OnInitDialog()内ではなく、CTestApp::InitInstance()の
頭でチェックしてreturn FALSEで抜けるべきではないか。

編集 削除
PATIO  2008-03-11 13:27:21  No: 67810  IP: 192.*.*.*

通常、二重起動防止の処理に関しては既に書かれているように
CTestApp::InitInstanceですると思います。
ダイアログベースなのでしたら既に起動していた時は
CDialogクラスの派生クラスのDoModalを呼ぶ処理をしないで
return FALSEで終了するのが普通です。
既に別のプロセスで起動しているのであれば、
ウインドウを出す必要も無いと思いますし。

逆になぜCTestDlg::OnInitDialogでやっているかの方が疑問です。

編集 削除
PATIO  2008-03-11 13:29:29  No: 67811  IP: 192.*.*.*

Web上で出ているサンプルソースでも普通はCWinAppクラスの派生クラスの
InitInstanceで行なう例が挙がっていると思うのですけれど。

編集 削除
夏みかん  2008-03-11 19:19:22  No: 67812  IP: 192.*.*.*

タイトルより。
> 多重起動をOnInitDialogで行うには?
多重起動防止をOnInitDialogで記述しないといけないのか?

初めて多重起動防止処理を実装しているのなら
InitInstance()部分で記述すべきです。

http://www.ikuyama.net/ryo/mfc/mfc01.html

編集 削除
Ris  2008-03-11 19:50:54  No: 67813  IP: 192.*.*.*

みいさん、PATIOさん、夏みかんさん、
お返事どうもありがとうございます。

タイトル名を間違えてしまってました。
> ×  多重起動をOnInitDialogで行うには
  ○  多重起動防止をOnInitDialogで行うには
です。

それと、なぜ、OnInitDialogで処理をしているかも書くべきでした。
大変申し訳ありません。

アプリケーションはタイトルバーキャプションで判断出来ない状況にあります。
同じタイトルのウィンドウがあることが予想されます。

それで、SDKですと、
タイトル文字列とウィンドウクラス名を自分で指定するので、
CreateWindowを呼ぶ前から両方分かっているので良いのですが、
MFCだと、どうすべきか分かりませんでした。

なので、自分のアプリケーション自身のウィンドウクラス名が
取得出来るOnInitDialogで取得しようと思いました。


> Web上で出ているサンプルソースでも普通は

メモリリークばかり気にしていました。
今から多重起動防止のサンプルを探してみようと思います。

何か分かりましたらまた書き込ませて頂きます。
もし何かいい方法がありましたら、宜しければ教えてください。
宜しくお願いします。

編集 削除
シャノン  2008-03-12 15:20:24  No: 67814  IP: 192.*.*.*

参考になるでしょうか
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200304/03040053.txt

編集 削除
Ris  2008-03-15 22:58:43  No: 67815  IP: 192.*.*.*

シャノンさん、URLありがとうございます。

クラス名をリソースで指定することが出来ましたので、
皆さんのご指摘通りInitInstance()で防止を行うことにしました。

今度はウィンドウハンドルの問題で詰まっていますが、
なんとか出来そうな気がします(^^

まだ時間がかかってしまいそうですが、
実装出来ましたらまた報告致します<(。_。)>

編集 削除