このたび初めてお世話になります。
二重起動防止策については、ずいぶん過去ログとかに掲載されておりました
がサンプルコードを実験してみて、一度もヒットした試しがありません。
原因は分かりませんが、素人判断でDelphiのバージョンが違うのか
(今回は バージョン 5)、サンプルコードはFORM付きのアプリケーションで
すが、小生のはコンソールアプリケーションだからどこか違うのかと、
思いあぐんでいます。
勝手な事情ですが納期が迫っています、どなたか成功例をご存知の方、宜し
くご指導ください。
下記にプロジェクトの部分を参考までに掲載さしていただきました。
program liveif;
{$APPTYPE CONSOLE}
uses
SysUtils,
module1 in 'module1.pas' {DataModule1: TDataModule};
begin
datamodule1 := Tdatamodule1.create(nil);
try
datamodule1.LOGcount;
datamodule1.makefile;
datamodule1.ASdataread;
datamodule1.rename;
finally
datamodule1.free;
end;
end.
こんな感じでしょう。
uses節にwindows(Mutex用),Dialogs(showMessage用)を追加
const
FMutexStr:string = 'KENSASTR';
var
FMutex:THandle;
begin
FMutex := OpenMutex(MUTEX_ALL_ACCESS,False,PChar(FMutexStr));
if FMutex <> 0 then begin //すでに起動
//すでに起動している場合の処理
end else begin //ないとき
hMutex := CreateMutex(nil,False,FMutexStr); //Mutex設定
end;
//今までのコード
ReleaseMutex(hMutex); //Mutex解放
end;
HOtaさんありがとう御座いました。
早速実行してみました。
が現象は変わりませんでした。
下記の書き方に誤りがあるでしょうか。
program liveif;
{$APPTYPE CONSOLE}
uses
SysUtils, windows,dialogs,
module1 in 'module1.pas' {DataModule1: TDataModule};
const
FMutexStr: string = 'KENSASTR';
var
FMutex : THandle;
begin
// ここにプログラムコードを書いてください。
FMutex := OpenMutex(MUTEX_ALL_ACCESS,False,PChar(FMutexStr));
if FMutex <> 0 then
begin
exit;
end else begin
FMutex := CreateMutex(nil,False,PChar(FMutexStr));
end;
datamodule1 := Tdatamodule1.create(nil);
try
datamodule1.LOGcount;
datamodule1.makefile;
datamodule1.ASdataread;
datamodule1.rename;
finally
datamodule1.free;
releaseMutex(FMutex);
end;
end.
OpenMutexの結果が0以外であれば、Mutexのハンドルが返っています。
CloseHandleすべきです。
HOtaさんのコードで試しました?
このコードが正しく動くのを確認してから、正しく動くコードに変更を加えていけばよろしいかと思います。
結構、正しく動くコードを真似して書いてみても、見落としとか出てきますよ。
# 私がそうなので^^;
プロジェクトに下記コードを記述します
var
HWND, HAPP: THandle;
begin
Application.Initialize;
HWND := FindWindow(nil, 'Ratio55');
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(Taaa,aaa); //作成したフォーム名
Application.Run;
end;
ある条件の時に、正しく動作しませんが、試してみてください
クッキーさん返事が遅れて申し訳ありません。
実はまだ試していないので怒られそうですが
クッキーさんのサンプルコードはフォームがあるケースだと思います。
フォームのある場合は過去例でも試してみた結果うまく行っています。
が 今回の小生のコードはフォームなしのコンソールアプリケーション
です。
フォームあるなしでは考え方が違うのではないかと思っていますが
いかがでしょうか。HOtaさんのコードでもうまく行っていません。
これからクッキさんのコードを試して見ます。
色々サンプルを見てみました
一瞬,起動しますが取り合えずコンソールアプリでもOKです
uses
SysUtils,
windows,
dialogs;
const
Name = 'ユニークな名前';
var
hMutex:Thandle;
begin
hMutex := OpenMutex(MUTEX_ALL_ACCESS, False, Name);
if hMutex <> 0 then
begin
CloseHandle(hMutex);
Exit;
end;
hMutex := CreateMutex(nil, False, Name);
writeln('aaa');
readln;
end.
yukihiro さんありがとう御座いました。
早速実行してみました。
これは私の思い込みなのかもしれませんが、二重起動の防止とは
絶対に二重にRUNしないと思っておりました。が
まずWindows98で実行すると、二重にも三重にも立ち上がりしまいには
メモリー不足でパンクしてしまいます。
Windows NT serverで実行しますと、さすがにパンクはしませんが
お知らせいただいたように一瞬DOS画面がちらつきます。
OSによって違いがなぜ出るのでしょうか。お分かりでしたらお知らせ下さい
レスはずしてましたら申し訳ないです。
要点をまとめると
1.Windows98にて二重・三重と起動してしまう
最終的には、メモリ不足でパンク
2.WindowsNT Serverでは、二重・三重には起動しないが
DOS画面がちらつく
3.OSによって異なる挙動について
1.について
二重・三重起動したときに、CreateMutex及び、OpenMutexが
エラーを生成せずに、正常動作していますでしょうか?
ログを出力させ、APIの戻り値についてチェックしてみてください
(GetLasterror API関数によるチェックも忘れずに)
ログ出力ロジックが面倒であれば、起動から、5秒間〜10秒間
OpenMutex関数を呼びつづけ、最終的な戻り値で判定させてみるのも
一つの方法だと思います
Dateを使ってチェックされると良いと思います
2.ちらつきます
これは、PGが動作する際、OpenMutexによって二重起動しているかチェック
しているためです
ちらつきの回避策としては、
ショートカットアイコンでの「実行時の大きさ」を変更するなどです。
3.項目1の原因は、別として
Windows 95,Windows98 WindowsMEは16ビットOSです
Windows NT ,Windows 2000, Windows XPとは異なり
メモリ管理方法、プロセス管理方法他が異なります。
32ビットAPIが実装されてもしますが、わざわざ16ビットOS環境で
動作するようにされてます。(ただし、すべてのAPIかどうかは、不明)
そのため、動作挙動が期待したものと異なる可能性があります
文面より推測して記述している部分もあります。
ご期待している回答になってないかもしれません
参考までにお読みいただければ、幸いです。
> Windows 95,Windows98 WindowsMEは16ビットOSです
そんなことはありません。32ビットOSです。
実装が一部16ビットのまま、とかはありますけど。
> これは私の思い込みなのかもしれませんが、二重起動の防止とは
> 絶対に二重にRUNしないと思っておりました。
思いこみです。二重起動の禁止はOSレベルの制御ではなくプログラミングの問題
です。まず、自分が起動されなければ、ほかに起動しているかどうかを判断できません。
> > Windows 95,Windows98 WindowsMEは16ビットOSです
>
> そんなことはありません。32ビットOSです。
> 実装が一部16ビットのまま、とかはありますけど。
つっかさま、他皆様大変失礼しました。
以降発言には、気をつけます、
大変申し訳ありませんでした。
すいません酔ってます
私も思考錯誤市ながらの初心者です
質問の答えになっていないかもしれませんが
const
Name = 'ユニークな名前'; の
ユニークな名前 これは、内部名なので
なんでもかまいませんが、もし同じ名前のものが
何かのプログラムで使われていたら起動出来ないと
思います
あ〜名にを言ってんでしょうか まず、起動して
ユニークな名前がソフト内に有れば起動するとか
しないとかなので、一瞬起ち上がるんじゃないのか?
いいかげんでスンマセン。
追伸
僕の環境、WIN98SE、DELPHI6の無料のやつ
追伸の追伸
つっかさんの言う取りです
ふじっこさんの発言も大変勉強になりました
(1、と 2、)
3も、じゅうぶん有り得る(ある)事なので
此れからも意識していきたいです
おやすみなさい
皆様アドバイスありがとう御座いました。
最近のご意見はスキルの低い小生にとって、頭上で高度な話が飛び交って
いるような気がして、如何様にこの収束を図るか苦慮致しております。
ともかく、ふじっこさんの質問に答えます。
<要点をまとめると
<1.Windows98にて二重・三重と起動してしまう
< 最終的には、メモリ不足でパンク
<2.WindowsNT Serverでは、二重・三重には起動しないが
< DOS画面がちらつく
<3.OSによって異なる挙動について
<1.について
< 二重・三重起動したときに、CreateMutex及び、OpenMutexが
< エラーを生成せずに、正常動作していますでしょうか?
Win98ではエラーが起こりますが、Win NT,Win2000では起こりません。
< ログを出力させ、APIの戻り値についてチェックしてみてください
< (GetLasterror API関数によるチェックも忘れずに)
< ログ出力ロジックが面倒であれば、起動から、5秒間〜10秒間
< OpenMutex関数を呼びつづけ、最終的な戻り値で判定させてみるのも
< 一つの方法だと思います
< Dateを使ってチェックされると良いと思います
この件に付いてははスキルがない為、チェックできずじまいです。
お手すきの時にでも、実行方法を教えて頂ければトライしたいと思います。
っな具合です。
ありがとう御座いました。ご意見をお待ちいたします。
OpenMutexでの二重起動チェックをよく見かけますが
CreateMutex までに割り込みの可能性があります。
CreateMutexだけで行ってみてはどうでしょうか?
外していたらスミマセン
var
hMutex: THandle;
begin
hMutex:= CreateMutex(nil, False, UniqueName);
// 既にミューテックスオブジェクトが存在する場合
if (GetLastError = ERROR_ALREADY_EXISTS) then Exit;
〜 以下略
end;
ツイート | ![]() |