VBでは極めてマイナー。ここまで来ると本人の趣味。
さて、ここではミューテックスというものを使おう。私本人も100%理解しているというわけではないが、まあ、やってみましょう。今回の処理の流れを簡単に言うと、メモリー上に任意の名前を持つオブジェクトが存在するかを見て、存在するなら2重起動処理、存在しないなら、オブジェクトを作成した後、通常起動という感じ。 オブジェクトがメモリー上に存在するということは、他プロセスから参照できるということ。簡単に言うと全く違ったアプリケーションどうしで、共通の情報を参照できるってことになるかな。また、ミューテックスオブジェクトは1プロセスに1つしか作れないよ。 ここで注意することが1つある。 やってみて分かたんだけど、Visual Basic 開発環境では、アプリケーションからミューテックスオブジェクトを解放しても駄目であるということ。開発中のアプリケーションを Visual Basic から実行した場合、Visual Basic がアプリケーションのハンドル等を管理する。その結果、ミューテックスオブジェクトを作成しても、Visual Basic もそれを保持してしまいアプリケーションから解放しても解放できないのよ。従って、ミューテックスオブジェクトを削除するには Visual Basic を終了しなければならない。こんな事をすることは非常に面倒なので、実行ファイルから起動していればミューテックスを有効にし、Visual Basic 開発環境なら無効にするというようにする。本来なら GetModuleFileName API関数を使用してするべきなのであろうがここでは Debug.Print の性質を利用することにする。 Debug.Printは、開発環境においては有効だけど、コンパイルすると無視され実行ファイルには反映されない。従って、意図的にエラーを発生させることにより、その2つの判断ができる。簡単である。0で除算すればよい。実際コードで書いてみるとよく分かる。
'--------------------------------------------------------------------------- ' 関数名 : IsNotVBProject ' 機能 : Visual Basic の開発環境であるか調べる ' 引数 : なし ' 返り値 : True … 実行ファイル環境 ' False … Visual Basic の開発環境 '--------------------------------------------------------------------------- Public Function IsNotVBProject() As Boolean On Error Resume Next Debug.Print 1 \ 0 IsNotVBProject = CBool(Err.Number = 0) End Function さて、ミューテックス関連のAPI関数・定数・外部変数は以下の通り。 Private Declare Function OpenMutex Lib "Kernel32" Alias "OpenMutexA" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal lpName As String) As Long Private Declare Function CreateMutex Lib "Kernel32" Alias "CreateMutexA" (ByVal lpMutexAttributes As Long, ByVal bInitialOwner As Long, ByVal lpName As String) As Long Private Declare Function ReleaseMutex Lib "Kernel32" (ByVal hMutex As Long) As Long Private Declare Function CloseHandle Lib "Kernel32" (ByVal hObject As Long) As Long
Private Const SYNCHRONIZE = &H100000
'ミューテックスオブジェクトのハンドル
'メモリー共有する文字 APPNAME_ON_MEM は各自で好きなように変更してね。
'--------------------------------------------------------------------------- ' 関数名: IsMutexEntity ' 機 能: ミューテックスオブジェクトが作成されているか調べる ' 作成されていなかったら作成する ' 引 数: なし ' 返り値: True … ミューテックスオブジェクトが存在する ' False … ミューテックスオブジェクトが存在しない ' 備 考: 二重起動防止に使用する '--------------------------------------------------------------------------- Public Function IsMutexEntity() As Boolean 'ミューテックを開く hMutex = OpenMutex(MUTANT_ALL_ACCESS, 0&&, APPNAME_ON_MEM) 'ミューテックスオブジェクトが存在するならハンドルをクローズし、終了 If hMutex Then Call CloseHandle(hMutex) IsMutexEntity = True Exit Function End If 'ミューテックスオブジェクトを作成する hMutex = CreateMutex(0&, 0&&, APPNAME_ON_MEM) End Function '--------------------------------------------------------------------------- ' 関数名: ReleaseMyMutex ' 機 能: ミューテックスオブジェクトを解放する ' 引 数: なし ' 返り値: なし ' 備考 : IsMutexEntity を呼び出していたら必ずこの関数を呼ばなければならない '--------------------------------------------------------------------------- Public Sub ReleaseMyMutex() Call ReleaseMutex(hMutex) End Sub 使用例は以下の通り。 Private Sub Form_Load() 実行環境が Visual Basic 開発環境ではない If IsNotVBProject Then If IsMutexEntity Then Call MsgBox("2重起動です"):End End If End Sub Private Sub Form_Unload(Cancel As Integer) Call ReleaseMyMutex End Sub |