Práce s Mutex aneb má aplikace bude spuštěná jen jednou
V minulé lekci, Paralelní třída a PLINQ v C# .NET, jsme se naučili paralelní třídu.
Pokud je nežádoucí, aby se vaše aplikace spouštěla více krát, pak čtěte dál.
Mutual exclusion (zkráceně Mutex) zabraňuje více násobnému použití částí, které si nepřejme sdílet. Vytváří se s nějakým klíčovým slůvkem, nejčastěji při použití pro náš úkon s názvem aplikace. Pokud již proces s tímto mutexem běží, pak se to po vytvoření instance Mutexu dozvíme.
Používá se také například i v instalátorech - nelze přepsat soubory, když jsou používány,
Přesuňme se do souboru Program.cs, kde vytvoříme novou instanci Mutexu:
bool createdNew; Mutex appMutex = new Mutex(true, Application.ProductName, out createdNew);
Při vytvoření instance Mutexu je jeho výstupem také proměnná typu
boolean
ve které je uložena informace o tom, zda již mutex se
stejným jménem existuje nebo se právě teď vytvořil.
Nyní nám již nic nebrání v tom si přidat jednoduchou podmínku.
if (createdNew) Application.Run(new Form1()); else MessageBox.Show("Tato aplikace může být spuštěna pouze jednou!");
Ovšem toto, je uživatelsky nepřívětivé a lepší by bylo, kdyby se při dalším kliku na soubor aplikace zobrazila v popředí.
A proto si vytvoříme třídu SingleInstance
public static class SingleInstance { public const int HWND_BROADCAST = 0xffff; public static int WM_SHOWME = RegisterWindowMessage("MOJE_APLIKACE_ZOBRAZ_OKNO"); [DllImport("user32")] public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam); [DllImport("user32")] public static extern int RegisterWindowMessage(string message); public static void ShowForm() { SingleInstance.PostMessage( (IntPtr)SingleInstance.HWND_BROADCAST, SingleInstance.WM_SHOWME, IntPtr.Zero, IntPtr.Zero); } }
Bude nás zajímat proměnná WM_SHOME, která obsahuje klíč, pomocí kterého se v programu pak vykoná daná metoda. Doporučuji tedy klidně se rozepsat a napsat něco unikátního. Můžete takto i ovládat aplikaci. Pokud si vytvoříte více takových můžete je pak obdobným způsobem volat.
Metoda ShowForm vyšle signál v podobě zadné RegisterWindowMessage a ten aplikace zpracuje v daném Formu nejčastěji v tom hlavním:
protected override void WndProc(ref System.Windows.Forms.Message m) { if (m.Msg == SingleInstance.WM_SHOWME) { this.Show(); WindowState = FormWindowState.Normal; this.Activate(); } base.WndProc(ref m); }
Přepíšeme metodu WndProc a přidáme do ní podmínku, pokud je příkazem náš příkaz proveď zobrazení okna. Teď již určitě chápete jak primitivní je udělat si aplikaci, ze které můžete ovládat jinou aplikaci. Je to sice k ničemu, ale pobaví to
Do Program.cs nyní jen v else zavoláme SingleInstance.ShowForm();
Poznámky:
Stalo se mi, že výše uvedený způsob nefungoval. Řešení může být
následující: Zavolání metody appMutex.ReleaseMutex()
před
spuštěním programu. Ovšem i toto mě zklamalo. Přidal jsem tedy ještě
podmínku
Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length == 1)
.
Tedy podívám se, kolik procesů ze stejným názvem je spuštěno. Pokud jen
jeden (ten současný), pokračuji, jinak zobrazím okno aplikace.
Stáhnout
Stažením následujícího souboru souhlasíš s licenčními podmínkami
Staženo 355x (40.3 kB)
Aplikace je včetně zdrojových kódů v jazyce C#