二重起動防止について過去ログを調べたのですが、わからなかったので教えてください。
BefCalc.exeとMainCalc.exeという2つのexeを作成しました。
このexeのアプリケーションタイトルは同じ「計算システム」という名前です。
MainCalc.exeは単独でも起動でき、BefCalc.exeからも起動させるシステムとなります。
他システムでGlobalFindAtomを使用して二重起動防止をしていたので
参考にして以下のようなプログラムを作成しました。
==========================
var
Atm1: TAtom;
Atm2: TAtom;
ActiveHandle: THandle;
Basepath : string;
const
SYSTEM_TITLE = '計算システム';
begin
//GlobalFindAtomにプログラム名を渡してすでに登録済みかどうかを調べる
Atm1 := GlobalFindAtom(PChar(ExtractFileName(Application.ExeName))); //起動EXE
BasePath := ExtractFilePath(Application.ExeName);
BasePath := BasePath + 'BefCalc.exe'; //別EXE
Atm2 := GlobalFindAtom(PChar(BasePath));
try
//戻り値が0以外の時はすでに登録済み
if (Atm1 <> 0) or (Atm2 <> 0) then
begin
//メインウィンドウの名前でアプリケーションのハンドルを検索
ActiveHandle := FindWindow(nil, SYSTEM_TITLE);
//すでに起動しているので、前面に出すなどの処理を行う
if ActiveHandle <> 0 then
begin
showmessage('すでに起動しています。');
//アイコン状態なら元に戻す
if IsIconic(ActiveHandle) then
SendMessage(ActiveHandle, WM_SYSCOMMAND, SC_RESTORE, -1);
//見つかったアプリケーションを前面に表示
SetForeGroundWindow(ActiveHandle);
Exit;
end
else
GlobalDeleteAtom(Atm);
//プログラム実行
Atm := GlobalAddAtom(PChar(ExtractFileName(Application.ExeName)));
==========================
MainCalc.exeが起動しているときはMainCalc.exeが起動できない、
BefCalc.exeが起動しているときはBefCalc.exeが起動できないように
ということは出来ました。
しかし、MainCalc.exeが起動しているときはBefCalc.exeが起動しないように、
BefCalc.exeが起動しているときはMainCalc.exeは起動しないようにさせることが出来ません。
(Atm2が0で返ってくるため)
ちなみに、システム名が同じなのでFindWindowをtryの前に持ってきてハンドルを取得したのですが、
この方法ではうまくいかない場合があります。
例えば、システムと同じ名前のフォルダ名(計算システムというフォルダ)を作成し、
そのフォルダを開いていたらEXEを起動していなくても起動している状態となってしまいました。
このような場合はどのようにして二重起動防止をしたらよろしいですか?
よろしくお願いします。
こんな感じでしょうか
var
HWND,HAPP:THandle;
begin
Application.Initialize;
HWND := FindWindow(nil,'アプリタイトル');
if (HWND <> 0) then begin
//メインウィンドウがある場合、アプリケーションのハンドルを取得する
HAPP := GetWindow(HWND,GW_OWNER);
if (IsIconic(HAPP)) then
//アプリケーションがアイコン化されていた場合、元サイズにする
OpenIcon(HAPP);
//前面に移動させる
SetForegroundWindow(HAPP);
end else begin
Application.Title := 'アプリタイトル';
Application.CreateForm(TMainForm, MainForm);
Application.Run;
end;
返信ありがとうございます。
その方法では以下の場合におかしくなってしまいます。
>ちなみに、システム名が同じなのでFindWindowをtryの前に持ってきてハンドルを取得したのですが、
>この方法ではうまくいかない場合があります。
>例えば、システムと同じ名前のフォルダ名(計算システムというフォルダ)を作成し、
>そのフォルダを開いていたらEXEを起動していなくても起動している状態となってしまいました。
他に何か方法はないでしょうか?
Mutex をつかった方法のコンポがいっぱいありますよ。検索してみたらいかがですか。
Mutexバージョンです
■使用するAPI関数
OpenMutex(既存の名前付きミューテックスオブジェクトのハンドルを取得する)
CloseHandle(オブジェクトのハンドルをクローズする)
CreateMutex(ミューテックスオブジェクトを作成する)
ReleaseMutex(ミューテックスオブジェクトの所有権を解放する)
■アプリケーションの二重起動を防止する処理
program Project1;
uses
Forms,Windows,
Unit1 in 'Unit1.pas' {Form1};
{$R *.RES}
var
Mutex: Integer;
begin
//ミューテックスオブジェクトのハンドルを取得する
Mutex := OpenMutex(MUTEX_ALL_ACCESS, False, 'EX_Mutex');
if Mutex <> 0 then begin
// オブジェクトのハンドルをクローズする
CloseHandle(Mutex);
Exit;
end;
//ミューテックスオブジェクトを作成する
Mutex := CreateMutex(nil, False, 'EX_Mutex');
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
//ミューテックスオブジェクトの所有権を解放する
ReleaseMutex(Mutex);
end.
OpenMutex()としてからCreateMutex()とするというのは、割り込める余地があるので間違いです。
http://techtips.belution.com/ja/vc/0025/
なるほど!!勉強になりました。
こうなるかな。
program Project1;
uses
Windows,
Forms,
Unit1 in 'Unit1.pas' ;
{$R *.res}
const
MutexName = 'myMutex';
WindowClass = 'TForm1';
var
hMutex: THANDLE;
Wnd: HWnd;
AppWnd: HWND;
WindowTitle: String;
begin
WindowTitle := 'myMainFormTitle';
hMutex := CreateMutex(nil, False, MutexName);
if hMutex = 0 then Exit;
if GetLastError() = ERROR_ALREADY_EXISTS then
begin
Wnd := FindWindow(PChar(WindowClass), PChar(WindowTitle));
if Wnd <> 0 then
begin
AppWnd := GetWindowLong(Wnd, GWL_HWNDPARENT);
if AppWnd = 0 then AppWnd := Wnd;
{二重起動時の動作}
end;
Exit;
end;
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
ReleaseMutex(hMutex);
end.
お返事が遅くなり、すみませんでした。
たくさんの返信ありがとうございます。
Mutexを使ったやり方で試しましたが起動出来てしまいます。
失敗です・・・。
皆さんの返信を見ていると「同じEXEを起動出来ないようにする」という
方法を教えていただいてるような気がします。
私の表現が悪かったのではないかと思いますので、もう1度まとめます。
私がやりたいのは「このEXEが起動している時は別EXEを起動させない」
という方法を教えてほしいと思い、書き込みをしました。
例えば、EXE1が起動している時はEXE2は起動出来ないようにしたいのです。
この場合は、EXE2のプロジェクトファイル(dpr)に
「EXE1が起動していれば終了する。
EXE1が起動していなければ自身を起動する。」
という処理を書いてあげればいいと思っています。
しかし、どのようにEXE1が起動しているかを確認すればいいのかわかりません。
方法を教えてください。
よろしくお願いします。
> 皆さんの返信を見ていると「同じEXEを起動出来ないようにする」という
> 方法を教えていただいてるような気がします。
違います。同じ名前の Mutex はひとつしか作れない、ってことを利用しています。
ですから、えみさんの要望を満たしています。Exe1 も Exe2 も同じ名前の Mutex
を作れるかどうかで判断できます。
>BefCalc.exeとMainCalc.exeという2つのexeを作成しました。
>このexeのアプリケーションタイトルは同じ「計算システム」という名前です。
>MainCalc.exeは単独でも起動でき、BefCalc.exeからも起動させるシステムとなります。
>MainCalc.exeが起動しているときはMainCalc.exeが起動できない、
>BefCalc.exeが起動しているときはBefCalc.exeが起動できないように
>ということは出来ました。
>しかし、MainCalc.exeが起動しているときはBefCalc.exeが起動しないように、
>BefCalc.exeが起動しているときはMainCalc.exeは起動しないようにさせることが出来ません。
この要件を、起動時に制御するには 仕様的に無理が無いですか・・
BefCalc.exeの中から、起動する(単独起動ではない)MainCalc.exeは
別なEXE名にするとかしないと・・
>BefCalc.exeの中から、起動する(単独起動ではない)MainCalc.exeは
>別なEXE名にするとかしないと・・
そのときは、特別な起動パラメータ渡して、二重起動抑止ロジックの実行を迂回すると。どちらもプログラム可能なら簡単です。
jokさん、考えてみれば、そうですね。
組み合わせパターンばかりに頭が行っていました。
>BefCalc.exeとMainCalc.exeという2つのexeを作成しました。
と書かれているので、どちらも御自身で触れそうなので、OKでしょう。
ツイート | ![]() |