通常の二重起動防止方法は、いろいろサイトでヒントを得られる
ようなんですが、あとから起動した方を実行したいのです。
その際、先に起動したものは、それの終了処理を正常にさせたいのと、
後から起動した方の初期化等は、先のを閉じてから行いたいという
条件があります。
隠しファイルを作って、「すでに起動中フラグ」として
使うような方法でも構いませんので、できれば、
Win32 API を使わない方法でやりたく思っています。
何かヒントがあれば、よろしくお願いします。
Windows Me
Delphi 4
反応をいただけませんね・・。
「できれば・・・」なので、できないのなら、
API の使用もやむなしです。
よろしくご教授ください。
APIを使用しなければファイルですら作成できないと思いますが
思いつくのは、AtomやSendMessageなどでアプリ間の通信を行うことですかねぇ・・・
暇だったんで、実験しました。
(以下を参考に *.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回目に起動した
ウィンドウが閉じないということになりました。
みなさん、ありがとうございます。
おやおやさん
>APIを使用しなければファイルですら作成できないと思いますが
TStrings.SaveToFile でできそうに思いますが・・?
deldelさん
> 思いつくのは、AtomやSendMessageなどでアプリ間の通信を行うことですかねぇ・・・
そういう表現では、具体的にどのようにコーディングすれば良いのか
見当がつかないので、敬遠してたんですけどね・・。
調べればいいんですけど、自分にとっていろんな意味でキツイ状況です。
サンデー・プログラマなので、システムにまで深入りしてまで組むのなら
あきらめ・・と言うパターンです。
foreverさん
実験ソースありがとうございます。
メッセージの意味がほとんどわかりませんが、これからテストしてみたいと
思います。
# DOS の頃は、メモリー値を直接書き換えたり、ディスク上のファイルの一部を書き換えて起動して、終了時に戻す・・など、サーカス・プログラムを
多少やりましたけど、もう細かいことはしんどいと思うようになりまして・・。
隠しファイル・・って、見えててもいいので、単に、「使用上」ユーザーに直接
関係がない・・程度の意味でした、表現がまずくて、失礼しました。
↑
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 クラスの宣言が無いか間違っています。
・・と出て、コンパイル・エラーになりました。
もう少しあれこれ考えてみます。
Form1の名前を変更するときに
ソースコードを変更するのではなく
オブジェクトインスペクタで変更する方がよいのではないでしょうか。
Form1→WMCloseTest
慣れですので、がんばってください。
>foreverさん
他の投稿への書き込みも、
大変勉強になります。ありがとうございます。
Fusa さん、ありがとうございます。「それ」でした。なるほど・・。
クラス関係はほとんどさわらないので、Name の変更に気が回りませんでした。
これで、提示していただいたサンプルが動かせました。万年初心者の質問に
いろいろありがとうございました。
ツイート | ![]() |