Projekt nad którym pracuję składa się z czterech aplikacji (czterech osobnych programów); Każda z nich może być uruchomiona tylko w jednej instancji oraz samotnie - w jednym czasie nie mogą działać razem dwie lub więcej; Musi to tak działać globalnie, dla wszystkich zalogowanych użytkowników;
Do stworzenia takiego zabezpieczenia chcę wykorzystać globalne muteksy - według mnie nadają się idealnie; Jednak mam problem z tymi muteksami, bo nie do końca rozumiem jak one działają oraz jak, kiedy i kto ma zająć się ich zwalnianiem; W sieci jest bardzo dużo przykładów (jeśli chodzi o wykrywanie kolejnych instancji tego samego programu) jednak każdy z nich jest inny i ciężko mi się połapać;
Aby zabezpieczyć program przed wieloma instancjami, można użyć czegoś w ten deseń:
function CanRunApplication(): Boolean;
var
hMutex: THandle;
begin
hMutex := CreateMutex(nil, False, 'Global\MutexName');
Result := (hMutex <> 0) and (GetLastError() = ERROR_SUCCESS);
end;
No i dobra - jeśli muteks zostanie stworzony pomyślnie, funkcja zwróci True, w przeciwnym razie False; Tak utworzonego muteksu nie trzeba nigdzie zwalniać - system się tym zajmie po wyłączeniu programu; Każdy z tych czterech programów wchodzących w skład pakietu, tworzy sobie swój unikalny muteks, aby nie dało się go uruchomić kolejny raz i to działa super;
Główny program sprawdza muteksy przy rozruchu i w razie kolizji po prostu nie uruchamia się; Pozostałe trzy muszą wykonać sprawdzenie podczas działania, zanim zaczną grzebać i modyfikować pliki całego pakietu;
Napisałem sobie funkcję, która testuje utworzenie kolejno trzech mutekstów (takich jak pozostałe trzy programy z pakietu) i w razie kolizji któregoś z tych trzech nie rozpoczyna operacji na plikach pakietu; Użyłem do tego celu funkcji CreateMutex
i wykrywa uruchomiony inny program; Jednak nawet jeśli ten drugi zamknę (muteks zostanie automatycznie zwolniony), to kolejny test nadal wykrywa ten muteks i nadal nie przechodzi do kolejnego kroku (czyli coś spaprałem);
Problem w tym, że nie wiem czy do takiego testu użyć CreateMutex
czy OpenMutex
(czy może jeszcze czegoś innego), a także nie rozumiem jakie ma znaczenie parametr bInitialOwner
tej pierwszej (czytałem dokumentację);
Funkcja która mnie interesuje, powinna wyglądać w ten sposób:
const
{ nazwy mutekstów pozostałych aplikacji z pakietu }
MUTEX_NAME_FIRST = 'Global\MutexNameFirst';
MUTEX_NAME_SECOND = 'Global\MutexNameSecond';
MUTEX_NAME_THIRD = 'Global\MutexNameThird';
type
{ pierwsze trzy oznaczają uruchomioną inną aplikację z pakietu }
TPackageAppKind = (pkaFirst, pkaSecond, pkaThird, pkaAlone);
function PackageAppIsRunning(): TPackageAppKind;
begin
{
sprawdzenie muteksu pierwszej innej aplikacji z pakietu
Exit(pkaFirst) - jeśli pierwsza jest uruchomiona
sprawdzenie muteksu drugiej innej aplikacji z pakietu
Exit(pkaSecond) - jeśli druga jest uruchomiona
sprawdzenie muteksu trzeciej innej aplikacji z pakietu
Exit(pkaThird) - jeśli trzecia jest uruchomiona
}
{ jeśli żadna nie jest uruchomiona zwracamy ostatni enum }
Result := pkaAlone;
end;
I teraz w jaki sposób poprawnie sprawdzić, czy któraś z pozostałych aplikacji jest uruchomiona? Użyć CreateMutex
czy OpenMutex
? Jeśli uda się utworzyć muteks którejś z pozostałych aplikacji to jak i w jakich warunkach go zwolnić? Brać pod uwagę uchwyt, GetLastError
czy i to i to?
W razie gdyby coś jeszcze nie było jasne to postaram się podać; Choć mam wrażenie, że i tak za dużo napisałem; Dzięki z góry za pomoc.