Windows API'de bir programın sadece bir defa çalışmasını sağlama

Yazar: Admin

Kategori: Yazılım

Windows API ile yaptığımız programın bazen sadece bir defa çalışmasını sağlamak isteyebiliriz.

Bu işlemi gerçekleştirmek için, Windows CreateMutex() fonksiyonunu kullanabiliriz.


HANDLE WINAPI CreateMutex(
  _In_opt_ LPSECURITY_ATTRIBUTES lpMutexAttributes,
  _In_     BOOL                  bInitialOwner,
  _In_opt_ LPCTSTR               lpName
);  

Programı çalıştırdığımızda, başlangıçta kullanılan CreateMutex() fonksiyonu başarılı bir şekilde işlem yaparsa, yeni bir mutex nesnesi oluşturur ve bu nesneyi gösteren bir HANDLE geri döndürür. Eğer fonksiyon düzgün bir şekilde çalışmazsa, NULL bir değer geri döndürür.


HANDLE hMutex;

hMutex = CreateMutex(NULL, TRUE, TEXT("MyApplication"));

Yukarıda yer alan "MyApplication" ifadesinin yerine herhangi bir karakter dizisi kullanabiliriz.

Eğer daha önceden CreateMutex() fonksiyonu ile lpName parametresine bir değer atanarak isimli bir mutex nesnesi oluşturulduysa, CreateMutex() fonksiyonunu ikinci kez kullandığımızda, mevcut mutex nesnesinin HANDLE değerini geri döndürür.

CreateMutex() fonksiyonundan sonra, GetLastError() fonksiyonunu kullandığımızda ise, GetLastError() fonksiyonu ERROR_ALREADY_EXISTS değerini geri döndürür.

GetLastError() fonksiyonunun ERROR_ALREADY_EXISTS değerini geri döndürdüğü tespit edildiğinde, CloseHandle() fonksiyonu ile yeni oluşturulan mutex nesnesi kapatılır ve programdan çıkılarak, programın çalışması sona erdirilir.


HANDLE hMutex;

hMutex = CreateMutex(NULL, TRUE, TEXT("NitrasApp"));
if (GetLastError() == ERROR_ALREADY_EXISTS) {
    CloseHandle(hMutex);
    return 0;
}  

Programın son hali aşağıdaki şekilde olacaktır:


#include <windows.h>

/* Windows fonksiyon bildirimi yapar */
LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);

/* Sınıf adını global bir değişkene atar */
char szClassName[ ] = "WinAPIWindowsApp";
/* HINSTANCE cinsinden global bir değişken bildirimi */
HINSTANCE ghInst;

int WINAPI WinMain (HINSTANCE hThisInstance,
                    HINSTANCE hPrevInstance,
                    LPSTR lpszArgument,
                    int nCmdShow)
{
    HWND hwndMain;           /* Program penceresine ait Handle */
    MSG messages;            /* Programa gönderilen mesajların kaydedildiği yer */
    WNDCLASSEX wincl;        /* Pencere değerlerini içeren yapı */
	
    HANDLE hMutex;

    hMutex = CreateMutex(NULL, TRUE, TEXT("NitrasApp"));
    if (GetLastError() == ERROR_ALREADY_EXISTS) {
        CloseHandle(hMutex);
        return 0;
    }		
	
    /* Programın bellekteki halinin Handle değeri global bir değişkene atanır */
    ghInst = hThisInstance;
	
    /* Pencere yapısına değer atama */
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure; /* Bu fonksiyon Windows tarafından çağrılır */
    wincl.style = CS_DBLCLKS;            /* Çift tıklamaları algılar */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Aktif ikon ve fare göstergesini kullanır */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL; /* Menü olmadığını gösterir */
    wincl.cbClsExtra = 0; /* Pencere sınıfından sonra ekstra byte olmadığını gösterir */
    wincl.cbWndExtra = 0; /* Yapı veya pencerenin instance değeri */
    /* Pencerenin arka planı için Windows geçerli rengini kullanır */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

    /* Pencere sınıfını kaydeder, hata oluşursa program sona erer */
    if (!RegisterClassEx (&wincl)) return 0;

    /* Sınıf kaydolmuştur, program oluşturulur */
    hwndMain = CreateWindowEx (
           0,                       
           szClassName,
           "WinAPI Temel Program",
           WS_OVERLAPPEDWINDOW,
           CW_USEDEFAULT,
           CW_USEDEFAULT,
           544,
           375,
           HWND_DESKTOP,
           NULL,
           hThisInstance,
           NULL
           );

    /* Pencere oluşturmada problem olursa programı sona erdirir. */
    if (!hwndMain) return 0;
		   
    /* Pencerenin ekranda görünmesini sağlar. */
    ShowWindow (hwndMain, nCmdShow);
    /* Pencereyi günceller */    
    UpdateWindow(hwndMain);

    /* Message döngüsünü çalıştırır. GetMessage() 0 değeri verene kadar devam eder.*/
    while (GetMessage (&messages, NULL, 0, 0) > 0)
    {
        /* Sanal tuş mesajlarını karakter mesajlarına çevirir. */
        TranslateMessage(&messages);
        /* Mesajları WindowProcedure() fonksiyonuna gönderir. */
        DispatchMessage(&messages);
    }

    CloseHandle(hMutex);	
	
    /* Program dönüş değeri 0'dır - Bu değeri PostQuitMessage() verir. */
    return messages.wParam;
}

/* Bu fonksiyon Windows'un DispatchMessage() fonksiyonu tarafından çağrılır. */

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)                  /* Mesajlara gerekli işlemi yapar. */
    {
        case WM_DESTROY:
            PostQuitMessage (0);      /* WM_QUIT değerini mesaj kuyruğuna gönderir */
            break;
        default:                      /* İşlem yapmadığımız mesajlar için */
            return DefWindowProc (hwnd, message, wParam, lParam);
    }

    return 0;
}