「入れ替わり型」の二重起動防止方法は?

解決


メルル  2006-04-25 13:01:10  No: 21180

通常の二重起動防止方法は、いろいろサイトでヒントを得られる
ようなんですが、あとから起動した方を実行したいのです。
その際、先に起動したものは、それの終了処理を正常にさせたいのと、
後から起動した方の初期化等は、先のを閉じてから行いたいという
条件があります。

隠しファイルを作って、「すでに起動中フラグ」として
使うような方法でも構いませんので、できれば、
Win32 API を使わない方法でやりたく思っています。
何かヒントがあれば、よろしくお願いします。

Windows Me
Delphi 4


メルル  2006-04-26 00:55:59  No: 21181

反応をいただけませんね・・。
「できれば・・・」なので、できないのなら、
API の使用もやむなしです。
よろしくご教授ください。


おやおや  2006-04-26 01:01:16  No: 21182

APIを使用しなければファイルですら作成できないと思いますが


deldel  2006-04-26 01:02:08  No: 21183

思いつくのは、AtomやSendMessageなどでアプリ間の通信を行うことですかねぇ・・・


forever  2006-04-26 03:11:20  No: 21184

暇だったんで、実験しました。
(以下を参考に *.dpr に書いてください。)
二重起動防止と大差ないです。

program Project1;

uses
  Forms,
  Windows,Messages,
  Unit1 in 'Unit1.pas' {WMCloseTest};

{$R *.RES}
procedure TerminatePreviousOne;
var
    Mtx: hwnd;
    Wnd: hwnd;
begin
    Mtx:= OpenMutex(MUTEX_ALL_ACCESS, False, '_WMCLOSE_TEST_');
    if Mtx<>0 then
    begin
        //TWMCloseTest ... メインフォームのクラス名
        //nil の部分には、メインフォームのキャプションを指定することも可能です
        wnd:= FindWindow('TWMCloseTest',nil);
        if wnd<>0 then
        begin
            SendMessage(wnd,WM_CLOSE,0,0);
        end;
    end;

    Mtx:= CreateMutex(nil,True,'_WMCLOSE_TEST_');
    if GetLastError<>0 then
        CloseHandle(Mtx);
end;

begin
  Application.Initialize;
  TerminatePreviousOne;
  Application.CreateForm(TWMCloseTest, WMCloseTest);
  Application.Run;
end.

他のアプリケーションとクラス名やキャプションが
重複するなど識別が困難な場合は工夫する必要があると思います。

_WMCLOSE_TEST_の部分も、ユニークで他と衝突し内容にしてください。

P.S.
CreateMutexやってGetLastErrorだけでいけるかと思ったけど
だめだった。CreateMutexやって既存のが見つかった場合
CloseHandleするから、今回起動したほうのMutexが開かれていない
という状況になって、3回目の起動の時、2回目に起動した
ウィンドウが閉じないということになりました。


メルル  2006-04-26 03:54:10  No: 21185

みなさん、ありがとうございます。

おやおやさん
>APIを使用しなければファイルですら作成できないと思いますが
TStrings.SaveToFile でできそうに思いますが・・?

deldelさん
> 思いつくのは、AtomやSendMessageなどでアプリ間の通信を行うことですかねぇ・・・

そういう表現では、具体的にどのようにコーディングすれば良いのか
見当がつかないので、敬遠してたんですけどね・・。
調べればいいんですけど、自分にとっていろんな意味でキツイ状況です。
サンデー・プログラマなので、システムにまで深入りしてまで組むのなら
あきらめ・・と言うパターンです。

foreverさん
実験ソースありがとうございます。
メッセージの意味がほとんどわかりませんが、これからテストしてみたいと
思います。

# DOS の頃は、メモリー値を直接書き換えたり、ディスク上のファイルの一部を書き換えて起動して、終了時に戻す・・など、サーカス・プログラムを
多少やりましたけど、もう細かいことはしんどいと思うようになりまして・・。


メルル  2006-04-26 04:50:04  No: 21186

隠しファイル・・って、見えててもいいので、単に、「使用上」ユーザーに直接
関係がない・・程度の意味でした、表現がまずくて、失礼しました。


メルル  2006-04-26 05:52:33  No: 21187


function FileSetAttr(const FileName: string; Attr: Integer): Integer;
でできるようでした。

////////

提示していただいたものそのままでは、
[エラー] Project1.dpr(36): 未定義の識別子 : 'TWMCloseTest'
[エラー] Project1.dpr(36): 未定義の識別子 : 'WMCloseTest
・・だったので、

とりあえず、
  Application.CreateForm(TForm1, Form1);
こちらでテストしてみたところ「雰囲気」大丈夫なようでした。

ユニット側のクラス名等も工夫しななければならようでした。

で、ユニット側を下のようにして、

type
  TWMCloseTest = class(TForm)
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  WMCloseTest: TWMCloseTest;

implementation

・・プロジェクトをサンプルの通りにしてみたところ、

モジュール Unit1でエラーが発生しました。
TForm1 クラスの宣言が無いか間違っています。

・・と出て、コンパイル・エラーになりました。

もう少しあれこれ考えてみます。


Fusa  2006-04-26 06:32:58  No: 21188

Form1の名前を変更するときに
ソースコードを変更するのではなく
オブジェクトインスペクタで変更する方がよいのではないでしょうか。

Form1→WMCloseTest

慣れですので、がんばってください。

>foreverさん
他の投稿への書き込みも、
大変勉強になります。ありがとうございます。


メルル  2006-04-26 06:54:30  No: 21189

Fusa さん、ありがとうございます。「それ」でした。なるほど・・。
クラス関係はほとんどさわらないので、Name の変更に気が回りませんでした。
これで、提示していただいたサンプルが動かせました。万年初心者の質問に
いろいろありがとうございました。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加