VB.NETで二重起動チェックを実施する

二度目まして!当社の新人プログラマー(業界歴7年目)わっくんです!

少し前の実体験になりますが、業界ではあるあるなトラブルに遭遇しました。
随分前にリリースされたアプリで、ユーザー様から「このアプリ、何重にも起動出来るけど、何で?」というお問い合わせを頂きました。そんな馬鹿な…と思いながら、実際に動かしてみると、確かに!これはいけません!
仕様書にはしっかりと「アプリが既に起動している場合は処理を終了する」と記載されていましたが、ソースを見てみると残念ながら二重起動の防止がされていませんでした(泣)

簡単に今回のアプリの仕様をご説明しますと、

  1. アプリを実行する
  2. 初期処理で二重起動チェックを実施する
      →既にアプリが起動している場合はアプリを起動しない
  3. 画面を表示する
という仕様なのですが、「初期処理で二重起動チェックを実施する。」が残念ながら出来ていなかった(厳密には、二重起動チェックの処理の書き方が間違っていた。)というオチです。
というわけで、今回はアプリが二重に起動しているかのチェック処理についてご紹介しようと思います。

目次

1. 二重起動について
2. 二重起動チェックを実装する
2-1. Mutexを使用して二重起動をチェックする
2-2. アプリケーションのプロセス名を判定して二重起動をチェックする
3. まとめ

1. 二重起動について
アプリケーションを起動する時、アイコンをクリックしてアプリケーションを立ち上げると思います。excelとかwordとかメモ帳だったらクリックしていくつも立ち上げても構わないと思いますが、冒頭の事例の様に、業務アプリでは二重起動は防ぎたいことが多いです。
例えば、アプリを二重に立ち上げて、更新系の機能を同時に触ってDBにデッドロックがかかったり、パッケージ製品やサードパーティ製品のライセンスエラーになったりと、残念なことが色々とある場合は、その端末での二重起動(多重起動)は回避する必要があります。
ただ、先に述べたように、二重起動しても良いよというアプリの場合には二重起動チェックを実装する必要はありません。

2. 二重起動チェックを実装する
2-1. Mutexを使用して二重起動をチェックする
二重起動のチェックにはいくつか方法がありますが、本記事ではMutexクラスを利用した二重起動チェックとプロセスチェックによる二重起動チェックを紹介します。ただし、Mutexクラスはmainメソッドでしか利用出来ないので、エントリポイントをmainメソッドに指定する必要があります。
詳しくは以前私が書いたこちらの記事をご覧ください。


_
Shared Sub Main()
'Mutexオブジェクトを作成する
Dim objMutex As New System.Threading.Mutex(False, "MyApplicationName")
'ハンドル判定用
Dim bHasHandle As Boolean = False
Try
Try
'ミューテックスの所有権を確認
bHasHandle = objMutex.WaitOne(0, False)
Catch ex As System.Threading.AbandonedMutexException
'ミューテックスを解放しないで終了した場合
bHasHandle = True
End Try
'ミューテックスの所有権を確認
If bHasHandle = False Then
'終了処理をここに記述
End If

'アプリケーション起動処理をここに記述する

Finally
If bHasHandle Then
'ミューテックス解放
objMutex.ReleaseMutex()
End If
objMutex.Close()
End Try
End Sub
Mutexを使用した場合は上記の様に実装してみて下さい。ただ、起動処理を入れてないので、ご自身で実装する場合は起動処理を実装してからデバッグして下さい。
また、Main()メソッドを終了する際に、Finally句にMutexクラスのオブジェクト解放を入れましょう。アプリケーション終了時にMutexクラスのオブジェクトを解放してくれます。

2-2. アプリケーションのプロセス名を判定して二重起動をチェックする
スタートアップがSub main()でない場合は二重起動チェックが出来ないのではないか?と考える方がいるかもしれません。安心してください、Main()メソッドを記述せず、フォームロードをスタートアップとしている場合は、アプリケーションのプロセスチェックによって二重起動チェックが出来ます。


'実行アプリケーションのプロセス名を取得
Dim strThisProcess As String = System.Diagnostics.Process.GetCurrentProcess().ProcessName
'取得した同名のプロセスが他に存在するかを確認
If System.Diagnostics.Process.GetProcessesByName(strThisProcess).Length > 1 Then
'ここに終了処理を記述
End If
フォームロードの直下に記載するか、判定メソッドを作成して、フォームロード時に呼び出す方法で上記を実装してみましょう。

4. まとめ
・二重起動チェックはMutexとプロセスチェックの方法がある。
・Mutexクラスを利用して二重起動チェックを実施する場合は、Main()メソッドに処理を記述すること。

二重起動チェックにお困りの方は、是非試してみて下さい!