Detekce a řízení spouštění aplikace - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

Detekce a řízení spouštění aplikace

27. února 2001, 00.00 | V některých případech nás může zajímat, zda je v systému již spuštěna jiná instance naší aplikace, popřípadě chceme omezit počet spuštěných instancí této aplikace. Ukážeme si zde 3 způsoby s vysvětlením jejich omezení a výhod..

V některých případech nás může zajímat, zda je v systému již spuštěna instance naší aplikace, popřípadě můžeme chtít omezit počet spuštěných instancí této aplikace. Ukážeme si zde 3 způsoby s vysvětlením jejich omezení a výhod:

1. Pomocí FindWindow

Tato metoda je sice nejjednodušší, ale není 100% spolehlivá. Spočívá v použití API funkce FindWindow, která hledá v celém systému okno, které odpovídá zadaným parametrům, jimiž jsou název třídy okna a název okna:

HWND FindWindow(LPCTSTR lpClassName, LPCTSTR lpWindowName);

Pomocí FindWindow tedy budeme hledat okno naší aplikace a pokud nám funkce vrátí platný handle, naše aplikace již běží. Nejdříve uvedu upravený kód funkce WinMain:

 

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
 // přidaný kód
 Application->Title = "";
 HWND hPrev = FindWindow(NULL, "MojeAplikace_1.00");
 if ( hPrev )
 {
  MessageBox(NULL, "Tato aplikace je již spuštěna !", "Nelze spustit", MB_ICONEXCLAMATION);
  SendMessage(hPrevInstance, WM_SYSCOMMAND, SC_RESTORE, 0);
  return 0;
 }
 else
 {
  Application->Title = "MojeAplikace_1.00";
  MessageBox(NULL, "Start povolen !", "OK", MB_ICONINFORMATION);
 }

// puvodni kod
 try
 {
  Application->Initialize();
  Application->CreateForm(__classid(TForm1), &Form1);
  Application->Run();
 }
 catch (Exception &exception)
 {
  Application->ShowException(&exception);
 }
 return 0;
}

Nejdříve musíme změnit jméno okna této spuštěné instance, abychom nenalezli "sami sebe". V případě, že nám funkce FindWindow vrátí platný handle okna, znamená to (s jistou nespolehlivostí, jak si řekneme), že tato aplikace je již v systému spuštěna.
V čem je její nespolehlivost? Za prvé vycházíme z toho, že název okna naší aplikace (pozor - není to hlavní formulář aplikace - v tom případě by spolehlivost byla velice nízká) se během běhu aplikace nezmění. Pak bychom toto okno nenalezli. Za druhé pokud je aplikace spuštěna dvakrát, nebo i vícekrát, v rychlém sledu za sebou (třeba opakovaným rychlým klikáním na jejího zástupce na ploše), vzhledem k multitaskingu může být funkce FindWindow u druhého spuštění volána dříve, než u prvního spuštění dojde k ukončení procesu vytvoření okna, což fyzicky nějakou dobu trvá. Pak opět první instanci aplikace nenalezneme.
Ukážeme si tedy další metody:

2. Použití Mutexu

Mutexy jsou objekty, které mohou "vidět" všechny aplikace v systému. Mutexy jsou pojmenované a jméno mutexu musí být jednoznačné, nemohou tedy v systému existovat dva nebo více mutexů. V aplikaci se tedy pokusíme vytvořit vlastní mutex. Pokud nepůjde vytvořit, znamená to, že již běží instance naší aplikace, která jej vytvořila před námi. Před ukončením aplikace musíme samozřejmě mutex opět zrušit. Celý postup je vidět na příkladu upravené funkce WinMain.

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
 HANDLE hMutex = CreateMutex(NULL,TRUE, "MojeAplikace");
 if (GetLastError() == ERROR_ALREADY_EXISTS )
 {
  if (hMutex)
   CloseHandle(hMutex);
  MessageBox(NULL, "Tato aplikace je již spuština !", "Nelze spustit", MB_ICONEXCLAMATION);
  return 0;
 }
MessageBox(NULL, "Start povolen !", "OK", MB_ICONINFORMATION);
 // puvodni kod
 try
 {
  Application->Initialize();
  Application->CreateForm(__classid(TForm1), &Form1);
  Application->Run();
 }
 catch (Exception &exception)
 {
  Application->ShowException(&exception);
 }
 // "zrušení" mutexu
 ReleaseMutex(hMutex);
 CloseHandle(hMutex);
 return 0;
}

3. Použití semaforu

Pokud chceme omezit počet spuštěných instancí na nějaké konkrétní číslo, můžeme využít tzv. semafory. Použijeme funkci

HANDLE CreateSemaphore(
    LP_SECURITY_ATTRIBUTES lpSemaphoreAttributes,
    LONG lInitialCount,
    LONG lMaximumCount,
    LPCTSTR lpName);

Jak semafory fungují? Parametr lInitialCount (musí být v rozmezí 0 až lMaximumCount) určuje počáteční stav semaforu. Stav semaforu je signalizován, pokud tento počet je větší než 0. Tento počet je snížen o 1, když tzv. čekající funkce uvolní vlákno čekající na semafor, a zvýšen o hodnotu uvedenou při volání funkce

BOOL ReleaseSemaphore(
    HANDLE hSemaphore,
    LONG lReleaseCount,
    LPLONG lpPreviousCount);

Nejlépe to uvidíte opět na příkladě funkce WinMain:

WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
 HANDLE hSemaphore = CreateSemaphore(NULL, 3, 3, "SemaforMojeAplikace");
 if ( hSemaphore && WaitForSingleObject(hSemaphore, 0) != WAIT_OBJECT_0 )
 {
  CloseHandle(hSemaphore);
  MessageBox(NULL, "Aplikace muže být spuštěna pouze třikrát !",  "Nelze spustit", MB_ICONEXCLAMATION);
  return 0;
 }
 MessageBox(NULL, "Start povolen !", "OK", MB_ICONINFORMATION);
 try
 {
  Application->Initialize();
  Application->CreateForm(__classid(TForm1), &Form1);
  Application->Run();
 }
 catch (Exception &exception)
 {
  Application->ShowException(&exception);
 }
 ReleaseSemaphore(hSemaphore, 1, NULL);
 CloseHandle(hSemaphore);
 return 0;
}

V tomto případě je vytvořen object semaphore s maximálním počtem 3. Dále je použita funkce

DWORD WaitForSingleObject(
    HANDLE hHandle,
    DWORD dwMilliseconds);

Tato funkce skončí, když objekt je v "signalizovaném stavu", nebo když vyprší časový limit. V případě, že časový limit je nastaven na nulu, jako je tomu v našem případě, funkce otestuje stav objektu a okamžitě skončí. Pokud je návratová hodnota funkce rovna WAIT_OBJECT_0, znamená to, že stav objektu (tedy našeho semaforu) je "signalizován".

Zde si můžete stáhnout ukázkové projekty:

Pomocí FindWindow

Pomocí Mutexu

Pomocí Semaphore

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: