2

特定のアプリケーション (app.exe など) が単一インスタンスかどうかを効率的に調べる方法を探しています。私はこれらの次のソルを考えました:

  1. CreateProcess() を 2 回実行し、そのアプリケーションのインスタンスが 2 つ以上実行されているかどうかを確認しますか? いいえの場合は、単一インスタンス アプリケーションです。しかし、これは効率的ではありません。
  2. CreateProcess() を実行し、1 ~ 2 秒待ちます。このインスタンスが強制終了された場合 (インスタンスが既に実行されているため)、単一インスタンス アプリになります。

しかし、私は上記の両方のソルに納得していません。Windowsでそれを行う他の効率的な方法はありますか?

そのアプリケーションの既に実行中のインスタンス (存在する場合) を強制終了したり変更したりしないことに注意してください。

4

6 に答える 6

7

逆に考えてみてください。プログラムを作成するとき、それが単一インスタンスか複数インスタンスかをどのように指定しますか? 他のプログラムが、実行せずにプログラムからその情報を取得できる方法はありますか? (この質問に答えたら、質問に対する答えが得られます。)

単一インスタンスか複数インスタンスかは実行時に決定され、実行時の条件に基づく可能性があるため、この問題は一般的に解決できません。たとえば、一部のアプリケーションは「複数インスタンスの場合もあれば、単一インスタンスの場合もある」: アプリケーションを実行してドキュメント X を開き、次にドキュメント Y を開くと、2 つのインスタンスが取得されます。しかし、ドキュメント X を開いてから再度ドキュメント X を開くと、2 つのインスタンスが 1 つに折りたたまれます。他のアプリケーションには、単一インスタンスか複数インスタンスかを選択できる構成スイッチがある場合があります。あるいは、彼らはコインを投げて、裏の場合は単一インスタンス、表の場合は複数インスタンスになることを決定するかもしれません。

于 2011-11-12T15:37:46.090 に答える
1

これを行う方法はまったくありません。アプリケーションがミューテックスをチェックし、インスタンスが既に実行されていることをユーザーに伝えるメッセージボックスを作成し、ユーザーがそれを閉じた場合にのみアプリケーションを強制終了するとどうなりますか? いくつかの共有リソース、ミューテックス、共有ファイルを介して相互排除を確実にするさまざまな方法があり、レジストリ キーを設定することもできますが、方法は無制限です。

于 2011-11-12T15:35:07.307 に答える
1

最良の方法は、Mutex (相互排他的) と呼ばれる同期オブジェクトを使用することです。あなたはそれをグーグルするかもしれません。次のコードが役立つと思います。

//---------------------------------------------------------------------------
WINAPI _tWinMain(HINSTANCE, HINSTANCE, LPTSTR, int)
{
    try
    {
        HANDLE hMutex=OpenMutex(MUTEX_ALL_ACCESS,0,"SIns");
        if (!hMutex) {
            //Mutex doesn’t exist. This is the first instance so create the mutex.
            //in this case app name is SIns (Single Instance)
            hMutex=CreateMutex(0,0,"SIns");
            Application->Initialize();
            Application->MainFormOnTaskBar = true;
            Application->CreateForm(__classid(TfMain), &fMain);
            Application->Run();
            ReleaseMutex(hMutex);
        }
        else{
            //This is not single. The prev instance is already running 
            //so informing about it 
            //remember that if it finds prev instance we're activating it here
            //you may do whatsoever here ...... e.g. you may kill process or stuff like this:)
            ShowMessage("The program is already running. Switching to ...");
            HWND hWnd=FindWindow(0,"SIns");
            SetForegroundWindow(hWnd);
        }

    }
    catch (Exception &exception)
    {
        Application->ShowException(&exception);
    }
    catch (...)
    {
        try
        {
            throw Exception("");
        }
        catch (Exception &exception)
        {
            Application->ShowException(&exception);
        }
    }
    return 0;
}
//---------------------------------------------------------------------------
于 2011-11-12T15:17:57.073 に答える
0

この概念の問題は、一般的な環境では、アプリケーションが単一インスタンスであるかどうかを決定する明示的な静的データがないことです。続行する動作はありますが、動作を完全にテストすることはできません。

マルチインスタンスのアプリがあるが、すでに開いているファイルを開くことができない場合はどうなりますか?同じ有効なファイル名で2回テストすると、1つのプロセスしか作成されませんが、他のコマンドライン引数を使用すると、2つのプロセスが存在します。これは単一インスタンスのプログラムですか?

このため、「単一インスタンス」は明確に定義されたプログラムのカテゴリではないと主張することもできます。

于 2011-06-29T19:45:56.203 に答える
0

ミューテックスを使用できます...次のコードでそのようなチェックを行います:

bool insureApplicationUniqueness(HANDLE& mutexHandle)
{
    mutexHandle=CreateMutexW(NULL,true,UNIQUE_INSTANCE_MUTEX_NAME);
    if( mutexHandle&&(ERROR_ALREADY_EXISTS==GetLastError()))
    {
        CloseHandle(mutexHandle);
        return false;
    }
    return true;
}

ただし、これは、ソースコードがあなたのものであり、チェックが実行中の別のインスタンスであるアプリケーション用です。

于 2011-06-29T07:34:08.840 に答える
0

通常の解決策は、ある種のロック ファイルを使用することです。たとえば、従来の Unix では、アプリケーションはファイルを作成することから開始し (ファイルが存在する場合でも成功します)、そのファイルへのリンクを作成しようとします (アトミック アクション)。それが失敗した場合、アプリケーションはすぐにそれ自体を強制終了します。Windows では、共有モード をCreateFile 同じ効果に使用できます。共有モード 0 でファイルを開き、それが失敗した場合は終了します。(Unix ソリューションでは、プロセスがクラッシュした場合にロックが解除されるため、手動でクリーンアップする必要があります。Windows ソリューションでは、システムがクラッシュした場合にロックが解除されます。)

于 2011-06-29T07:32:19.353 に答える