VC.NET ~ 二重起動のチェック

前置き

アプリの二重起動をチェックする方法の1つを紹介します。名前付きMutexのようなシステムに一意なオブジェクトを利用する方法もありますが、ここでは別の方法で。

System::Diagnostics::Processクラスを使う

bool duplicated()
{
  Process^ me = Process::GetCurrentProcess();
  array<Process^>^ ps = Process::GetProcessesByName(me->ProcessName);
  return ps->Length >= 2;
}

このコードでは、GetProcessesByName()により、自プロセスと同じ名前を持つプロセスの配列を取得しています。自プロセスも含まれるので、ps[]のサイズは少なくとも1ですが、二重起動した場合は2以上になります。

この方法の欠点は、偶然、同じ名前の別アプリがあった場合に誤認識してしまうところです。ここで言う「アプリの名前」や「プロセスの名前」は、たぶん、exeファイルの名前のことです(wiki.exeならwiki)。

そこで、さらに厳密に調べる場合は、exeのパスを使う方法があります。

bool duplicated()
{
  Process^ me = Process::GetCurrentProcess();
  array<Process^>^ ps = Process::GetProcessesByName(me->ProcessName);
  if ( ps->Length <= 1 ) return false;

  String^ myPath = me->MainModule->FileName;
  int c = 0;
  for ( int i = 0; i < ps->Length; i++ ) {
    String^ path = ps[i]->MainModule->FileName;
    if ( !path->Equals(myPath, StringComparison::CurrentCultureIgnoreCase) ) continue;
    c++;
    if ( c >= 2 ) return true;
  }
  return false;
}

FileName属性にはexeのフルパスが入っています。やっかいなことに、ドライブレターが大文字だったり小文字だったりするので、大文字小文字を無視して比較しましょう。

しかし、この方法にも欠点があります。別々のフォルダに置いた同じexeファイルによる二重起動が判別できないのです。

そこで、アプリのリソース情報(バージョンとか会社名とか)を使って同一性を確認する方法も試してみました。アプリにリソース情報を埋め込むにはapp.rcを使います。

  • app.rc
1 VERSIONINFO
BEGIN
  BLOCK "StringFileInfo"
  BEGIN
      BLOCK "041104B0"
    BEGIN 
      VALUE "CompanyName",     "GPSOFT\0"
      VALUE "FileVersion",     "1, 0, 0, 1\0"
    END
  END
  BLOCK "VarFileInfo" 
  BEGIN 
    VALUE "Translation", 0x411, 1200
    END
END

VALUE要素の右辺は書き換え可能です。0411とか04B0(1200)といった数字はキャラクタセットに関する設定です。

では、会社名を使って二重起動をチェックしてみましょう。

bool duplicated()
{
  Process^ me = Process::GetCurrentProcess();
  array<Process^>^ ps = Process::GetProcessesByName(me->ProcessName);
  if ( ps->Length <= 1 ) return false;

  String^ company = me->MainModule->FileVersionInfo->CompanyName;
  int c = 0;
  for ( int i = 0; i < ps->Length; i++ ) {
    if ( ps[i]->MainModule->FileVersionInfo->CompanyName != company ) continue;
    c++;
    if ( c >= 2 ) return true;
  }
  return false;
}

.NETの時代に古い(managedでない)リソースを使うのもナンですけどね。

Last modified:2011/11/23 16:33:32
Keyword(s):
References:[.NETアプリ開発]
This page is frozen.