5

Windows 環境で、プログラムの 2 つのインスタンスを同時に実行したくありません。

関連している

Mutex を使用して、同じプログラムの複数のインスタンスが安全に実行されないようにしていますか?

4

10 に答える 10

12

それがあなたのプログラムである場合、Windowsで可能な限り短いバージョン:

int main(int argc, char** argv)
{
    CreateMutexA(0, FALSE, "Local\\$myprogram$"); // try to create a named mutex
    if(GetLastError() == ERROR_ALREADY_EXISTS) // did the mutex already exist?
        return -1; // quit; mutex is released automatically

    // ... program code ...
}

単純なチェックだけが必要な場合は、非常に複雑になる必要はありません...

于 2013-01-05T21:28:04.620 に答える
10

先に進む前に、シナリオを少し検討する必要があると思います。「同じプログラムを複数回実行する」ことには、さまざまな解釈があります。たとえば、あなたは

  1. マシンごとに 1 回
  2. ログオン セッションごとに 1 回
  3. ユーザーごとに 1 回

これらはすべて、似ていますが、異なる解決策を持っています。

説明するのが最も簡単なのは、マシンごとです。この場合、名前付き Mutex を作成します。プログラムごとに 1 回の起動でこのミューテックスを取得する必要があります。成功した場合、プログラムは実行され、プロセスの存続期間中ミューテックスを保持します。そうしないと、他のプログラムが実行中であり、すぐに終了します。

残念ながら、このアプローチには欠点もあります。あなたのプログラムを台無しにしたい場合は、同じ名前のミューテックスを作成できます。これにより、プログラムはミューテックスを保持している人を特定できず、何かがミューテックスを保持しているだけで、インスタンスを実行できなくなります。

于 2009-04-29T03:24:31.260 に答える
9

アプリケーションの最初のインスタンスの起動時にミューテックスを作成できます。2 番目のインスタンスを防止するには、mutex が使用されているかどうかを確認するだけです。

実際、この目的でミューテックスを使用することについて質問がありました。JaredPar の回答をご覧ください。

注: 「1 つのインスタンス」を (すべてのユーザーではなく) ユーザーのセッション内でのみ適用する場合は、ローカル ミューテックスを使用できます。

于 2009-04-29T03:18:03.447 に答える
3

最良の方法は、ミューテックスを使用することです。Mutex オブジェクトの使用を参照してください。

于 2009-04-29T03:18:46.470 に答える
3

別の簡単な解決策は、適切に一意のグローバル名前付きイベント (おそらく GUID 文字列) を作成し、起動時にその存在を確認することです。存在する場合、アプリのインスタンスは既に開始されています。そうでない場合は、イベントが自動的に作成され、引き続き実行できます。例:

// for brevity, a complete set of error handling has been omitted

m_hEvent = CreateEvent(NULL, TRUE, FALSE, szMyUniqueNamedEvent);

switch (GetLastError)
{
    // app is already running
    case ERROR_ALREADY_EXISTS:
    {
        CloseHandle(m_hEvent);

        // now exit
        break;
    }

    // this is the first instance of the app
    case ERROR_SUCCESS:
    {
        // global event created and new instance of app is running,
        // continue on, don't forget to clean up m_hEvent on exit
        break;
    }
}
于 2009-04-29T07:36:33.417 に答える
2

これは、boost.interrprocessを使用してスクリプト化したクラスです。これを使用して、GUI と CLI のバージョンを同期します。

あなたはそれが役に立つかもしれません:

#pragma once

#include <boost/interprocess/windows_shared_memory.hpp>
#include <boost/interprocess/mapped_region.hpp>

#ifndef max
#define max(a,b)            (((a) > (b)) ? (a) : (b))
#endif

using boost::interprocess::windows_shared_memory;
using boost::interprocess::mapped_region;
using boost::interprocess::open_or_create;
using boost::interprocess::read_write;
using boost::interprocess::interprocess_exception;

class CProcessMutex
{

public:
    CProcessMutex()
        : m_region()
        , m_status(false)
    {
        initSharedMemory();
        Increment();
    }

    ~CProcessMutex()
    {
        Decrease();
    }

public:
    int GetCount()
    {
        return m_status ? *(static_cast<unsigned char*>(m_region.get_address())) : 0;
    }

private:
    void initSharedMemory()
    {
        try
        {
            //Create a native windows shared memory object.
            windows_shared_memory shm (open_or_create, "shared_memory", read_write, 1);
            //Map the whole shared memory in this process
            m_region.swap(mapped_region(shm, read_write));
            m_status = true;
        }
        catch(interprocess_exception &ex)
        {
            ex.what();
            m_status = false;
        }
    }

    void Increment()
    {
        if(m_status) (*(static_cast<unsigned char*>(m_region.get_address())))++;
    }
    void Decrease()
    {
        if(m_status) (*(static_cast<unsigned char*>(m_region.get_address())))--;
    }
private:
    mapped_region m_region;
    bool m_status;
};

使い方は簡単です:

CProcessMutex pm;
size_t current_process_count = pm.GetCount();
if(current_process_count > 1)
{
 ...
}

そのため、並列処理の数を簡単に制限できます。

于 2009-04-29T04:39:05.357 に答える
2

Qt を使用する場合、QtSingleApplicationコンポーネントをダウンロードできます。

于 2009-04-29T11:47:19.603 に答える
1

他の人が示唆しているように、ミューテックスを使用してください。

MS のCreateMutex () ドキュメントには多くの有用な情報があり、プログラムの複数のインスタンスが実行されるのを防ぐためにミューテックスを使用する場合に具体的に対処しています。特に:

  • で呼び出しCreateMutex()bInitialOwner = FALSEから、待機関数 (例: WaitForSingleObject()) を呼び出して、1 つのインスタンスだけがミューテックスを取得するようにします。
  • サービス拒否攻撃が心配な場合は、代わりにロックされたファイルを使用することを検討してください。
于 2009-04-29T03:45:03.630 に答える
0

プログラムの起動時に、マシンで実行されているプロセスを列挙できます

次に、すでに実行されていることがわかったら、終了します

于 2009-04-29T03:52:06.657 に答える
-1

ウィンドウクラスが既に登録されているかどうかを確認できます。このMSDN エントリを見てください。

于 2009-04-29T03:15:29.643 に答える