多重起動防止

 @ FindWindow 関数を使用する方法
 A Mutex(ミューテックス)を使用する方法<その1>
 B Mutex(ミューテックス)を使用する方法<その2>

自分が行っているのは、Mutexの方なので
Mutexの方を説明します。


Mutex使用の多重起動防止までの流れ<その1>
 @ グローバルに、ミューテックスに使用するHANDLEを定義しておく。
 A OpenMutex () により、ミューテックスオブジェクトのハンドルを取得
 B if文により、もしミューテックスオブジェクトがオープンでき、ハンドルが取得出来れば、
   以前にアプリケーションが起動していると言うことなので、WinMain ()に riturn FALSE を送り、アプリケーションを終了させる。
 C アプリケーションが起動していなければ、CreateMutex () により、グローバルに定義しておいたハンドルに、ミューテックスオブジェクトを作成する。
 ※ CreateMutex () により、グローバルにミューテックスオブジェクトハンドルを作成しておくことにより、
   Aで、ミューテックスオブジェクトのハンドルを取得することができる。
 D アプリケーション終了前に、ミューテックスハンドルのリリース(開放)する。

Mutex使用の多重起動防止までの流れ<その2>
 @ グローバルに、ミューテックスに使用するHANDLEを定義しておく。
 A CreateMutex () により、グローバルに定義しておいたハンドルに、ミューテックスオブジェクトを作成する。
 B GetLastError () により、ERROR_ALREADY_EXISTING メッセージが来ているかのチェックする
 C ERROR_ALREADY_EXISTING メッセージだった場合、以前にアプリケーションが起動しているということなので、
   WinMain ()に riturn FALSE を送り、アプリケーションを終了させる。
 ※ CreateMutex () により、グローバルにミューテックスオブジェクトハンドルを作成しておくことにより、
 D アプリケーション終了前に、ミューテックスハンドルのリリース(開放)とクローズをする。


上記で述べた関数の説明
 OpenMutex () 関数
  HANDLE OpenMutex(DWORD fAccess, BOOL fInherit, LPCTSTR sMutexName);
 引数の説明
fAccessミューテックスオブジェクトの使用フラグ
fInherit取得ハンドルが、継承可能かの真偽(FALSE/TRUE)
sMutexNameオープンするミューテックスオブジェクト名
 戻り値
  オープンしたミューテックスオブジェクトのハンドル。
  ミューテックスオブジェクトのオープンに失敗した場合、NULLが返される。

 CreateMutex () 関数
  HANDLE CreateMutex(LPSECURITY_ATTRIBUTES pSAttr, BOOL fOwner, LPCTSTR sMutexName);
 引数の説明
pSAttrセキュリティ属性
fOwner作成時に所有権を取得するかの真偽(FALSE/TRUE)
sMutexName作成するミューテックスオブジェクト名
 戻り値
  作成したミューテックスオブジェクトのハンドル。
  ミューテックスオブジェクトの作成に失敗した場合、NULLが返される。
  既に、指定したミューテックスオブジェクトのハンドルが存在していた場合
  GetLastError () 関数により、ERROR_ALREADY_EXISTINGが返される

  • 使用例:サンプル<その1>

  • //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //_/                                                        _/
    //_/ Mutexサンプル<その1>                                  _/
    //_/ 赤字が、対象のコードです                               _/
    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    
    #include<windows.h>
    
    HANDLE g_hMutex;
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst,
                       LPSTR lpszCmdLine, int nCmdShow)
    {
        HWND hWnd;
        MSG msg;
        WNDCLASS wc;
    
        HANDLE hPrevMutex;
    
        hPrevMutex = OpenMutex(MUTEX_ALL_ACCESS, FALSE, "MutexTestSample"));
    
        if(hPrevMutex)
        {
            MessageBox(NULL, "既に起動しています。", "起動中", MB_OK);
            CloseHandle(hPrevMutex);
            return FALSE;
        }
    
        g_hMutex = CreateMutex(FALSE, 0, "MutexTestSample");
    
        if(!hPreInst)
        {
            wc.style         = CS_HREDRAW | CS_VREDRAW;
            wc.lpfnWndProc   = WndProc;
            wc.cbClsExtra    = 0;
            wc.cbWndExtra    = 0;
            wc.hInstance     = hInstance;
            wc.hIcon         = NULL;
            wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
            wc.hbrBackground = GetStockObject(WHITE_BRUSH);
            wc.lpszMenuName  = NULL;
            wc.lpszClassName = "Window";
            if (!RegisterClass(&wc))
                return FALSE;
        }
    
        hWnd = CreateWindow(
            wc.lpszClassName,
            "Mutexサンプル",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInstance,
            NULL);
    
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        ReleaseMutex(g_hMutex);
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
            default:
                return(DefWindowProc(hWnd, msg, wParam, lParam));
        }
        return 0;
    }








    ← グローバルに、ミューテックスハンドル宣言。










    ← ミューテックステスト用のハンドル宣言。
         
    ← ミューテックスハンドルを取得。

    ← もし、ミューテックスのハンドルが取得できれば、
      以前に、アプリケーションを起動していると言うことなので、
      テストに使ったハンドルをクローズし、
      WinMainに、FALSEを返し、アプリケーションを終了する。



    ← ミューテックスハンドルを取得 "できなければ"、
      ハンドルを作成する。






































    ← アプリケーション終了前に、ミューテックスハンドルをリリースする。

















  • 使用例:サンプル<その2>

  • //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    //_/                                                        _/
    //_/ Mutexサンプル<その2>                                  _/
    //_/ 赤字が、対象のコードです                               _/
    //_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/_/
    
    #include<windows.h>
    
    HANDLE g_hMutex;
    
    LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
    
    int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPreInst,
                       LPSTR lpszCmdLine, int nCmdShow)
    {
        HWND hWnd;
        MSG msg;
        WNDCLASS wc;
    
        g_hMutex = CreateMutex(FALSE, 0, "MutexTestSample");
    
        if(GetLastError() == ERROR_ALREADY_EXISTS)
        {
            MessageBox(NULL, "既に起動しています。", "起動中", MB_OK);
            return FALSE;
        }
    
        if(!hPreInst)
        {
            wc.style         = CS_HREDRAW | CS_VREDRAW;
            wc.lpfnWndProc   = WndProc;
            wc.cbClsExtra    = 0;
            wc.cbWndExtra    = 0;
            wc.hInstance     = hInstance;
            wc.hIcon         = NULL;
            wc.hCursor       = LoadCursor(NULL, IDC_ARROW);
            wc.hbrBackground = GetStockObject(WHITE_BRUSH);
            wc.lpszMenuName  = NULL;
            wc.lpszClassName = "Window";
            if (!RegisterClass(&wc))
                return FALSE;
        }
    
        hWnd = CreateWindow(
            wc.lpszClassName,
            "Mutexサンプル",
            WS_OVERLAPPEDWINDOW,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            CW_USEDEFAULT,
            NULL,
            NULL,
            hInstance,
            NULL);
    
        ShowWindow(hWnd, nCmdShow);
        UpdateWindow(hWnd);
    
        while (GetMessage(&msg, NULL, 0, 0))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        ReleaseMutex(g_hMutex);
        CloseHandle(g_hMutex);
        return msg.wParam;
    }
    
    LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
    {
        switch(msg)
        {
            case WM_DESTROY:
                PostQuitMessage(0);
                break;
            default:
                return(DefWindowProc(hWnd, msg, wParam, lParam));
        }
        return 0;
    }








    ← グローバルに、ミューテックスハンドル宣言。










    ← ミューテックスハンドルを作成。

    ← もし、GetLastError () から、
      ERROR_ALREADY_EXISTS メッセージが返されたら
      以前に、アプリケーションを起動していると言うことなので、
      WinMainに、FALSEを返し、アプリケーションを終了する。







































    ← アプリケーション終了前に、ミューテックスハンドルをリリースする。
    ← アプリケーション終了前に、ミューテックスハンドルをクローズする。


















    死影の月に戻る