Vytvoření aplikace WinUI s jednou instancí pomocí jazyka C#
Tento postup ukazuje, jak vytvořit aplikaci WinUI 3 s jednou instancí pomocí jazyka C# a sady Windows App SDK. Jednoinstanční aplikace umožňují mít současně spuštěnou pouze jednu instanci aplikace. Aplikace WinUI jsou ve výchozím nastavení víceinstanční. Umožňují spustit více instancí stejné aplikace současně. To se vztahuje na více případů. Na základě způsobu použití vaší aplikace můžete ale chtít implementovat jednu instanci. Při pokusu o spuštění druhé instance aplikace s jednou instancí se místo toho aktivuje pouze hlavní okno první instance. Tento návod demonstruje, jak implementovat single-instancing v aplikaci WinUI.
V tomto článku se dozvíte, jak:
- Vypněte vygenerovaný kód XAML
Program
- Definování přizpůsobené metody
Main
pro přesměrování - Testování jednoho instancengu po nasazení aplikace
Požadavky
Tento kurz používá Visual Studio a využívá šablonu prázdné aplikace WinUI. Pokud s vývojem pro WinUI začínáte, můžete ho nastavit podle pokynů v tématu Začínáme s WinUI. Tam si nainstalujete Visual Studio, nakonfigurujete ho pro vývoj aplikací pomocí WinUI a zároveň zajistíte, že máte nejnovější verzi WinUI a sadu Windows App SDK a vytvoříte projekt Hello World.
Až to uděláte, vraťte se sem, abyste se dozvěděli, jak projekt "Hello World" převést na aplikaci s jednou instancí.
Poznámka
Tento postup je založený na Vytvoření aplikace s jednou instancí (část 3) příspěvku na blogu ze série blogů o Windows na WinUI 3. Kód pro tyto články je k dispozici na GitHub.
Zakázání automaticky generovaného kódu programu
Před vytvořením jakýchkoli oken musíme co nejdříve zkontrolovat přesměrování. K tomu musíme definovat symbol "DISABLE_XAML_GENERATED_MAIN" v souboru projektu. Pokud chcete automaticky vygenerovaný kód programu zakázat, postupujte takto:
V Průzkumníku řešení klikněte pravým tlačítkem na název projektu a vyberte Upravit soubor projektu.
Definujte symbol DISABLE_XAML_GENERATED_MAIN. Do souboru projektu přidejte následující KÓD XML:
<PropertyGroup> <DefineConstants>$(DefineConstants);DISABLE_XAML_GENERATED_MAIN</DefineConstants> </PropertyGroup>
Přidání symbolu DISABLE_XAML_GENERATED_MAIN zakáže automaticky vygenerovaný kód programu pro váš projekt.
Definování třídy Program pomocí metody Main
Místo spuštění výchozí metody Main musí být vytvořen přizpůsobený soubor Program.cs. Kód přidaný do třídy Program umožňuje aplikaci kontrolovat přesměrování, což není výchozí chování aplikací WinUI.
Přejděte do Průzkumníka řešení, klikněte pravým tlačítkem na název projektu a vyberte Přidat | Třída.
Pojmenujte novou třídu
Program.cs
a vyberte přidat.Do třídy Program přidejte následující obory názvů a nahraďte všechny existující obory názvů:
using System; using System.Diagnostics; using System.Runtime.InteropServices; using System.Threading; using System.Threading.Tasks; using Microsoft.UI.Dispatching; using Microsoft.UI.Xaml; using Microsoft.Windows.AppLifecycle;
Nahraďte prázdnou třídu Program následujícím kódem:
public class Program { [STAThread] static int Main(string[] args) { WinRT.ComWrappersSupport.InitializeComWrappers(); bool isRedirect = DecideRedirection(); if (!isRedirect) { Application.Start((p) => { var context = new DispatcherQueueSynchronizationContext( DispatcherQueue.GetForCurrentThread()); SynchronizationContext.SetSynchronizationContext(context); _ = new App(); }); } return 0; } }
Metoda Main určuje, zda má aplikace po volání DecideRedirectionpřesměrovat na první instanci nebo spustit novou instanci.
Definujte metodu DecideRedirection pod metodou Main:
private static bool DecideRedirection() { bool isRedirect = false; AppActivationArguments args = AppInstance.GetCurrent().GetActivatedEventArgs(); ExtendedActivationKind kind = args.Kind; AppInstance keyInstance = AppInstance.FindOrRegisterForKey("MySingleInstanceApp"); if (keyInstance.IsCurrent) { keyInstance.Activated += OnActivated; } else { isRedirect = true; RedirectActivationTo(args, keyInstance); } return isRedirect; }
DecideRedirection určuje, jestli byla aplikace zaregistrována registrací jedinečného klíče, který představuje vaši instanci aplikace. Na základě výsledku registrace klíče může určit, jestli je spuštěná aktuální instance aplikace. Po zhodnocení situace metoda zjistí, zda přesměrovat, nebo dovolit spuštění nové instance aplikace. Metoda RedirectActivationTo se volá, když je přesměrování potřebné.
Dále vytvoříme metodu RedirectActivationTo pod metodou DecideRedirection spolu s požadovanými příkazy DllImport. Do třídy Program přidejte následující kód:
[DllImport("kernel32.dll", CharSet = CharSet.Unicode)] private static extern IntPtr CreateEvent( IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName); [DllImport("kernel32.dll")] private static extern bool SetEvent(IntPtr hEvent); [DllImport("ole32.dll")] private static extern uint CoWaitForMultipleObjects( uint dwFlags, uint dwMilliseconds, ulong nHandles, IntPtr[] pHandles, out uint dwIndex); [DllImport("user32.dll")] static extern bool SetForegroundWindow(IntPtr hWnd); private static IntPtr redirectEventHandle = IntPtr.Zero; // Do the redirection on another thread, and use a non-blocking // wait method to wait for the redirection to complete. public static void RedirectActivationTo(AppActivationArguments args, AppInstance keyInstance) { redirectEventHandle = CreateEvent(IntPtr.Zero, true, false, null); Task.Run(() => { keyInstance.RedirectActivationToAsync(args).AsTask().Wait(); SetEvent(redirectEventHandle); }); uint CWMO_DEFAULT = 0; uint INFINITE = 0xFFFFFFFF; _ = CoWaitForMultipleObjects( CWMO_DEFAULT, INFINITE, 1, [redirectEventHandle], out uint handleIndex); // Bring the window to the foreground Process process = Process.GetProcessById((int)keyInstance.ProcessId); SetForegroundWindow(process.MainWindowHandle); }
Metoda RedirectActivationTo zodpovídá za přesměrování aktivace na první instanci aplikace. Vytvoří popisovač události, spustí nové vlákno pro přesměrování aktivace a počká na dokončení přesměrování. Po dokončení přesměrování metoda přenese okno do popředí.
Nakonec definujte pomocnou metodu OnActivated pod metodou DecideRedirection:
private static void OnActivated(object sender, AppActivationArguments args) { ExtendedActivationKind kind = args.Kind; }
Testování jednotného instancování prostřednictvím nasazení aplikace
Až dosud jsme aplikaci testovali laděním ve Visual Studiu. Můžeme ale mít spuštěný pouze jeden ladicí program najednou. Toto omezení nám brání v tom, abychom věděli, jestli je aplikace jedna instance, protože nemůžeme stejný projekt ladit dvakrát současně. Pro přesný test nasadíme aplikaci do našeho místního klienta Windows. Po nasazení můžeme aplikaci spustit z plochy, jako byste měli s libovolnou aplikací nainstalovanou ve Windows.
Přejděte do Průzkumníka řešení, klikněte pravým tlačítkem na název projektu a vyberte Nasadit.
Otevřete nabídku Start a klikněte do vyhledávacího pole.
Do vyhledávacího pole zadejte název aplikace.
Kliknutím na ikonu aplikace z výsledku hledání spusťte aplikaci.
Poznámka
Pokud dojde k chybovému ukončení aplikace v režimu vydání, existují některé známé problémy s oříznutými aplikacemi v sadě Windows App SDK. V projektu můžete zakázat oříznutí nastavením vlastnosti PublishTrimmed na false pro všechny konfigurace sestavení v souborech vašeho projektu
.pubxml
. Další informace najdete v tématu tomto problému na GitHubu.Opakováním kroků 2 až 4 znovu spusťte stejnou aplikaci a zkontrolujte, jestli se otevře jiná instance. Pokud je aplikace s jednou instancí, první instance se místo otevření nové instance aktivuje.
Shrnutí
Veškerý zde popsaný kód je na GitHub, s větvemi pro různé kroky v původní Windows blog series. Kód specifický pro tento postup najdete ve větvi pro jednorázové použití.
main
větev je nejkomplexnější. Ostatní větve vám ukážou, jak se architektura aplikace vyvíjela.
Související obsah
vytváření instancí aplikací pomocí rozhraní API životního cyklu aplikace
vytvoření jedné instance aplikace (část 3)
ukázka WinAppSDK-DrumPad na GitHubu
Windows developer