2005年08月08日

アプリケーションの二重起動を抑制する方法

同じアプリケーションを複数起動し、
負荷分散や可用性を目的としたシステムもあれば、
同じアプリケーションが
二重起動されると困るシステムもあります。

今回はミューテックス(mutually exclusive)オブジェクトを利用し、
アプリケーションの二重起動を抑制する方法を紹介します。

一般的にミューテックスオブジェクトは、
マルチCPUプラットフォームをターゲットにした
複数のスレッドを並行処理させるアプリケーションで、
共有メモリなどの共有リソースを、
同時にアクセスさせないよう排他制御で使用します。

サンプルプログラムで利用するCreateMutex関数は、
名前付きまたは名前なしの
ミューテックスオブジェクトを作成または開きます。
関数が成功すると、
ミューテックスオブジェクトのハンドルが返ります。
この関数を呼び出す以前に
そのミューテックスオブジェクトが存在する場合は、
この関数は既存のオブジェクトに対するハンドルを返し、
GetLastError関数は「ERROR_ALREADY_EXISTS」を返します。

アプリケーションはCreateMutex関数を呼出す際に、
ミューテックスオブジェクトの名前を指定し、
同じアプリケーションが
この関数を以前に呼び出したか否かを判断し、
アプリケーションの二重起動であるか否かを判定します。

それではサンプルプログラムを参照し、
二重起動させない方法をお試し下さい。

使用例
unit DupCheckUnit;

interface

uses
 Classes, Controls, Dialogs, Forms,
 Graphics, Messages, SysUtils, Variants, Windows;

const
 WM_INITIALIZE = WM_USER + 101;

type
 TForm1 = class(TForm)
  procedure FormCreate(Sender: TObject);
  procedure FormDestroy(Sender: TObject);
 private
  FApName: String;
  FMutex: THandle;
  procedure OnMessage(
   var
pMsg: TMsg; var pHandled: Boolean); virtual;
  procedure Initialize;
 public
 end
;

var
 Form1: TForm1;

implementation

{$R *.dfm}

//--------------------------------------
procedure TForm1.FormCreate(Sender: TObject);
begin
 // アプリケーション変数を初期化する
 FMutex := 0;
 FApName := 'YourApplicationName';
 Application.OnMessage := Self.OnMessage;
 // 初期化イベントを自分自身に発生させる
 PostMessage(Self.Handle, WM_INITIALIZE, 0, 0);
end;

//--------------------------------------
procedure TForm1.FormDestroy(Sender: TObject);
begin
 // アプリケーションが使用したリソースを開放する
 if (FMutex <> 0) then
  CloseHandle(FMutex);
end;

//--------------------------------------
procedure TForm1.OnMessage(
 var pMsg: TMsg; var pHandled: Boolean);
begin
 Case pMsg.message of
 // 初期化イベントをハンドリングする
 WM_INITIALIZE:
  begin
   pHandled := True;
   Self.Initialize;
  end;
 end;
end;

//--------------------------------------
procedure TForm1.Initialize;
begin
 FMutex := CreateMutex(0, False, PChar(FApName));
 // この関数を呼び出す以前に
 // ミューテックスオブジェクトが存在する場合、
 // GetLastErrorは
 // ERROR_ALREADY_EXISTSを戻すので、
 // 既に同じアプリケーションが起動されていることになる

 if (GetLastError = ERROR_ALREADY_EXISTS) then
 begin
  MessageDlg(Format(
   'There is another instance of %s of running.',
    [FApName]), mtError, [mbOk], 0);
  PostMessage(Self.Handle, WM_QUIT, 0, 0);
 end;
end;

end.


関連書籍


Copyright guy@かしらもんじ でぇ〜

posted by guy at 07:19 | 起動編
×

この広告は1年以上新しい記事の投稿がないブログに表示されております。