外部アプリの2重起動防止

[戻る]
まりのちゃん 2006/07/03(月) 16:35:38
VC++ 6.0で開発しております。

過去スレから外部アプリの2重起動防止についてしらべ、
以下のような実装してみたのですがうまく行きません。

// 既に起動しているか?
if (::FindWindow(NULL,"test.exeに設定されているタイトル名") != NULL)
{
    return false;
}

// OpenVPNクライアントの起動
ShellExecute(NULL, "open", "C:\\Program Files\\TEST\\test.exe", NULL, NULL, 
SW_SHOWNORMAL); 

*test.exe(仮称)は私がVCアプリから起動しようとしている外部アプリケーションで
す。

なにがうまく行かないかというと、上記ロジックだとtest.exeを起動して
ウインドウがオープンしている状態であれば
"test.exeに設定されているタイトル名"がFindWindowで検知でき、
二重起動を防止できるのですが、
タスクトレイに常駐している状態でウインドウが開いていない状態では
うまく行きません。
どなたか良い方法をご存知方、実装方法をおしえていただけないでしょうか?

ちがう実装方法で、例えばタスクマネージャのプロセスに表示されいるイメージ名
で多重起動を防止できる方法などありましたら教えてください。

まりのちゃん 2006/07/03(月) 16:43:35
すみません。
情報がたりませんでしたので追加します。

作成しようとしているアプリは常駐プロセスではありません。
起動されたタイミングでtest.exeが起動しているか確認し、
起動していればtest.exeを起動せず終了する。
・・・というものです。

まりのちゃん 2006/07/03(月) 18:47:12
[[解決]]
お騒がせしました。
解決!?しました。

方法としましては、
PCで稼動しているプロセス名を全て取得する方法で
該当する〜.exeがあるか検索し、
あった場合は起動中とみなし
同exeは起動しないようにしました。
実装ロジックは以下です。

う〜んこれでいんでしょうか?
もっと簡単な実装方法ご存知の方いらっしゃましたら
レスをいただければと思います。

DWORD ProcessIDs[1000];
DWORD ProcessNum;
HMODULE Modules[1000];
DWORD ModuleNum;
char FileName[1000];
DWORD RetSize;
DWORD i, j;
HANDLE hProcess;
BOOL bResult;

CString exeName = "test.exe";
CString readName;
int findPos = -1;

/* プロセスの一覧と数を取得 */
EnumProcesses(ProcessIDs, sizeof(ProcessIDs), &RetSize);
ProcessNum = RetSize / sizeof(DWORD);

for(i=0; i<ProcessNum; i++)
{
    hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, 
ProcessIDs[i]);

    if(hProcess == NULL)
    {
        printf("\tオープン失敗.\n");
    } else {
        /* プロセス中のモジュールの一覧を取得 */
        bResult = EnumProcessModules(hProcess, Modules, sizeof(Modules), 
&RetSize);
        if(bResult) {
            ModuleNum = RetSize / sizeof(HMODULE);

            /* 各モジュールのファイル名を表示 */
            for(j=0; j<ModuleNum; j++) {
                GetModuleFileNameEx(hProcess, Modules[j], FileName, 1000);
           readName = FileName;
           findPos = readName.Find(exeName, 0);
          if (findPos != -1)
          {
              break;
          }
            }

            if (findPos != -1)
            {
                break;
            }
        }
        CloseHandle(hProcess);
}

if (findPos == -1)
{
    WinExec("C:\\Program Files\\TEST\\test.exe",SW_SHOWNORMAL);
}

とるまリンゴ 2006/07/04(火) 13:30:07
ミューテックスを使って2重起動防止する方法は、如何でしょう?
これならば、
Googleで「ミューテックス VC」で検索すると、色々でてきますよ。

(例)
・http://techtips.belution.com/ja/vc/0025/http://hp.vector.co.jp/authors/VA019882/tips/data/data01.htm
  006 アプリケーションの2重起動を防止する

大三元 2006/07/04(火) 15:10:33
CxxxDlgが元のダイアログクラスだとすると、
xxx.cppのInitInstance()の
// 標準的な初期化処理
// もしこれらの機能を使用せず、実行ファイルのサイズを小さくしたけ
//  れば以下の特定の初期化ルーチンの中から不必要なものを削除して
//  ください。
のコメントの後に、
以下の記述を追加すればできますよ!!


// アプリケーションの二重起動防止
CString MutexName;
CWnd* pWnd;

MutexName.Format("Link20060703 %s",m_pszExeName);
CMutex mutex(FALSE,MutexName);
    
// 実行中
if(mutex.Lock(0) == FALSE)
{
    pWnd = CWnd::FindWindow(NULL,m_pszAppName);
    if(pWnd != NULL)
    {
    // 実行中のアプリケーションを前面に移動
    pWnd->SetForegroundWindow();
    }
    return FALSE;
}

まりのちゃん 2006/07/04(火) 15:18:39
すみません。スレの最初の発言で書かなかったでんすが
ミューテックスも試したのですができなかったんですよ〜。
やり方がまちがっていたんでしょうかね〜?
ミューテックスってそもそも以下のような判定できんるんでしょうか?
例えば
VCアプリからWinEXEで秀丸エディタを起動
↓
その後VCアプリを再実行
 if:秀丸エディタがいたら起動処理を行わない。
  else:秀丸エディタ
  ↑ここの判定部分

まりのちゃん 2006/07/04(火) 15:27:18
まちがえました
 if:秀丸エディタがいたら起動処理を行わない。
  else:秀丸エディタ起動
  ↑ここの判定部分

ようはVCで作成したアプリではないものを
判定できるかです。

大三元さんありがとうございます。
大三元さんの方法時間があるときに試してみます。

PATIO 2006/07/04(火) 16:09:07
ミューテックスでは自分が全く関与できないソフトを排他する事は出来ません。
なので、今の方法で何とかするしかないと思います。

ミューテックスを使う場合と言うのは基本的に自分が作成しているアプリや
システム内での排他制御になると思います。

dairygoods 2006/07/04(火) 16:17:13
ミューテックスを使った方法は、
自分のアプリケーションが多重起動しないように
する時に使うテクニックですので、
外部アプリケーションの場合は使えないでしょう。

外部アプリのEXEファイルパスが分かっているなら、
そのファイルを排他読み取りオープンできるかどうかで
確認するのはいかがでしょうか。

#偶然に、さらに別のアプリがそのEXEを排他読み取りオープン
#している場合も引っかかってしまいますが。

まりのちゃん 2006/07/04(火) 16:24:23
現行のままでいくことにします。
みなさん情報ありがとうございました。

古いスレッドには追加発言できません。