Skip to content
Closed
32 changes: 32 additions & 0 deletions src/Controls/samples/Controls.Sample/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Diagnostics.Metrics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using Maui.Controls.Sample.Controls;
Comment on lines +7 to 8
using Maui.Controls.Sample.Pages;
Comment on lines 5 to 9
using Maui.Controls.Sample.Services;
Expand All @@ -29,6 +30,8 @@
#if ANDROID
using Android.Gms.Common;
using Android.Gms.Maps;
#elif WINDOWS
using Microsoft.Windows.AppLifecycle;
#endif

namespace Maui.Controls.Sample
Expand Down Expand Up @@ -286,6 +289,7 @@ static string GetTags(IEnumerable<KeyValuePair<string, object?>> tags) =>
events.AddWindows(windows => windows
// .OnPlatformMessage((a, b) =>
// LogEvent(nameof(WindowsLifecycle.OnPlatformMessage)))
.OnAppInstanceActivated((application, args) => HandleWindowsAppInstanceActivated(application, args))
.OnActivated((a, b) => LogEvent(nameof(WindowsLifecycle.OnActivated)))
.OnClosed((a, b) => LogEvent(nameof(WindowsLifecycle.OnClosed)))
.OnLaunched((a, b) => LogEvent(nameof(WindowsLifecycle.OnLaunched)))
Expand All @@ -310,6 +314,34 @@ static bool LogEvent(string eventName, string? type = null)
Debug.WriteLine($"Lifecycle event: {eventName}{(type == null ? "" : $" ({type})")}");
return true;
}

#if WINDOWS
static bool HandleWindowsAppInstanceActivated(Microsoft.UI.Xaml.Application application, AppActivationArguments args)
{
LogEvent(nameof(WindowsLifecycle.OnAppInstanceActivated), args.Kind.ToString());

// This sample opts into single-instancing from the MAUI lifecycle callback
// instead of a custom Program.cs entry point.
var keyInstance = AppInstance.FindOrRegisterForKey("Maui.Controls.Sample");

if (!keyInstance.IsCurrent)
{
// The WinAppSDK single-instance guidance redirects the activation and then
// terminates the losing instance immediately. Using Kill here avoids leaving
// a headless process around that can continue to hold build outputs open.
keyInstance.RedirectActivationToAsync(args).AsTask().GetAwaiter().GetResult();

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 AI-Generated Review (multi-model)

[major] Async and Threading Safety — Same blocking pattern as the library code: keyInstance.RedirectActivationToAsync(args).AsTask().GetAwaiter().GetResult() runs inside HandleWindowsAppInstanceActivated, invoked as a WindowsLifecycle.OnAppInstanceActivated handler on the UI thread (either directly from OnLaunched or dispatched from MauiWinUIApplication.HandleAppInstanceActivated). This is presented to app authors as recommended single-instancing boilerplate, but it teaches the same deadlock/hang-prone anti-pattern flagged in the product code instead of awaiting the redirect.

Process.GetCurrentProcess().Kill();
return true;
Comment thread
mattleibow marked this conversation as resolved.
}

if (Application.Current?.Windows.FirstOrDefault() is Window window)
// Redirected activations can arrive off the UI thread, so hop through the
// MAUI window dispatcher before re-activating the existing window.
window.Dispatcher.Dispatch(() => Application.Current.ActivateWindow(window));

return false;
}
#endif
});

// Adapt to dual-screen and foldable Android devices like Surface Duo, includes TwoPaneView layout control
Expand Down
5 changes: 4 additions & 1 deletion src/Core/src/LifecycleEvents/Windows/WindowsLifecycle.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
namespace Microsoft.Maui.LifecycleEvents
using Microsoft.Windows.AppLifecycle;

namespace Microsoft.Maui.LifecycleEvents
{
public static class WindowsLifecycle
{
public delegate bool OnAppInstanceActivated(UI.Xaml.Application application, AppActivationArguments args);
public delegate void OnActivated(UI.Xaml.Window window, UI.Xaml.WindowActivatedEventArgs args);
Comment on lines 5 to 8

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR description and metadata refer to a new OnAppActivation(...) hook, but the implementation introduces OnAppInstanceActivated(...) instead. Please update the PR description (or rename the API) so the documented public surface matches the code that will ship.

Copilot uses AI. Check for mistakes.
public delegate void OnClosed(UI.Xaml.Window window, UI.Xaml.WindowEventArgs args);
public delegate void OnLaunched(UI.Xaml.Application application, UI.Xaml.LaunchActivatedEventArgs args);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
{
public static class WindowsLifecycleBuilderExtensions
{
public static IWindowsLifecycleBuilder OnAppInstanceActivated(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnAppInstanceActivated del) => lifecycle.OnEvent(del);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 AI-Generated Review (multi-model)

[major] Public API baseline — This PR adds Core Windows public API surface (WindowsLifecycle.OnAppInstanceActivated, its generated Invoke, the WindowsLifecycleBuilderExtensions.OnAppInstanceActivated(...) extension method, and MauiWinUIApplication.OnAppInstanceActivated(...)), but src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt was not updated. The sibling Windows lifecycle delegates/extensions are tracked in PublicAPI.Shipped.txt, so the Core public API analyzer will reject these additions until the corresponding Unshipped entries are added.

public static IWindowsLifecycleBuilder OnActivated(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnActivated del) => lifecycle.OnEvent(del);
public static IWindowsLifecycleBuilder OnClosed(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnClosed del) => lifecycle.OnEvent(del);
public static IWindowsLifecycleBuilder OnLaunching(this IWindowsLifecycleBuilder lifecycle, WindowsLifecycle.OnLaunching del) => lifecycle.OnEvent(del);
Expand Down
52 changes: 50 additions & 2 deletions src/Core/src/Platform/Windows/MauiWinUIApplication.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System;
using System;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Maui.Hosting;
using Microsoft.Maui.LifecycleEvents;
using Microsoft.Windows.AppLifecycle;

namespace Microsoft.Maui
{
Expand All @@ -20,9 +21,17 @@ public abstract class MauiWinUIApplication : UI.Xaml.Application, IPlatformAppli

protected override void OnLaunched(UI.Xaml.LaunchActivatedEventArgs args)
{
// Windows running on a different thread will "launch" the app again
LaunchActivatedEventArgs = args;

var launchActivation = AppInstance.GetCurrent().GetActivatedEventArgs();

// A running WinUI app can be activated again without rebuilding the MAUI application.
// Reuse the existing services and let activation handlers short-circuit the relaunch path.
if (_application != null && _services != null)
{
if (launchActivation is AppActivationArguments activatedEventArgs && OnAppInstanceActivated(activatedEventArgs))

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 AI-Generated Review (multi-model)

[moderate] Regression Prevention and Test Coverage — When OnLaunched fires again for an already-running instance (_application != null && _services != null), this calls OnAppInstanceActivated(activatedEventArgs) directly using AppInstance.GetCurrent().GetActivatedEventArgs(), while AppInstance.GetCurrent().Activated (line 91, wired up on the prior launch) remains subscribed via HandleAppInstanceActivated. If WinAppSDK delivers the same reactivation through both paths, WindowsLifecycle.OnAppInstanceActivated handlers (including WebAuthenticator.OnAppInstanceActivatedCallback) can run twice for one logical activation with no de-duplication guard. LifecycleEventOrderTests.Windows.cs's new OnAppInstanceActivatedFiresExactlyOnce test only covers the initial single-launch case, not this already-running-instance reactivation path, so a double-invocation regression here would go undetected.

return;

_services.InvokeLifecycleEvents<WindowsLifecycle.OnLaunching>(del => del(this, args));
_services.InvokeLifecycleEvents<WindowsLifecycle.OnLaunched>(del => del(this, args));
return;
Expand All @@ -37,6 +46,14 @@ protected override void OnLaunched(UI.Xaml.LaunchActivatedEventArgs args)

_services = applicationContext.Services;

// Future AppInstance activation callbacks need the app-level services to exist first.
RegisterForAppInstanceActivated();

// Run the initial activation after services are available, but before OnLaunching/window creation,
// so handlers can redirect or suppress the default startup flow.
if (launchActivation is AppActivationArguments initialActivation && OnAppInstanceActivated(initialActivation))
return;

_services.InvokeLifecycleEvents<WindowsLifecycle.OnLaunching>(del => del(this, args));

_application = _services.GetRequiredService<IApplication>();
Expand All @@ -48,10 +65,41 @@ protected override void OnLaunched(UI.Xaml.LaunchActivatedEventArgs args)
_services.InvokeLifecycleEvents<WindowsLifecycle.OnLaunched>(del => del(this, args));
}

protected virtual bool OnAppInstanceActivated(AppActivationArguments args)
{
var wasHandled = false;

_services?.InvokeLifecycleEvents<WindowsLifecycle.OnAppInstanceActivated>(del =>
{
// Preserve any earlier "handled" result so multiple listeners can participate safely.
wasHandled = del(this, args) || wasHandled;
});

return wasHandled;
}

void RegisterForAppInstanceActivated()
{
if (_isRegisteredForAppInstanceActivated)
return;

_isRegisteredForAppInstanceActivated = true;

// After startup, later file/protocol/redirected activations are delivered through AppInstance.
AppInstance.GetCurrent().Activated += HandleAppInstanceActivated;

void HandleAppInstanceActivated(object? sender, AppActivationArguments args)
{
OnAppInstanceActivated(args);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 AI-Generated Review (multi-model)

[major] Async and Threading SafetyAppInstance.Activated can be delivered on a non-UI thread for redirected/file/protocol activations, but this calls OnAppInstanceActivated(args) synchronously and therefore runs public MAUI lifecycle handlers off the WinUI UI thread. Handlers are likely to touch Application.Current, windows, or controls (the sample added in this PR does), which can throw cross-thread exceptions or race with startup. Dispatch this callback through the application/window DispatcherQueue (with a null/disposed guard) before invoking lifecycle delegates.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 AI-Generated Review (multi-model)

[major] Windows lifecycle threading — AppInstance.GetCurrent().Activated is raised by the Windows App SDK on a non-UI thread, but this handler calls OnAppInstanceActivated(args) directly. That runs every public WindowsLifecycle.OnAppInstanceActivated callback off the WinUI dispatcher, so app code that touches Window, DispatcherQueue, or other UI-affine state from this lifecycle hook can fail intermittently on redirected/protocol activations. Capture/use the WinUI DispatcherQueue (or the MAUI application dispatcher once available) before invoking lifecycle handlers, or make the off-thread contract explicit and keep MAUI-owned handlers from touching UI state.

}
Comment on lines +90 to +104
}

public static new MauiWinUIApplication Current => (MauiWinUIApplication)UI.Xaml.Application.Current;

public UI.Xaml.LaunchActivatedEventArgs LaunchActivatedEventArgs { get; protected set; } = null!;

bool _isRegisteredForAppInstanceActivated;

IServiceProvider? _services;

IApplication? _application;
Expand Down
6 changes: 5 additions & 1 deletion src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
#nullable enable
#nullable enable
Microsoft.Maui.LifecycleEvents.WindowsLifecycle.OnAppInstanceActivated
override Microsoft.Maui.Platform.MauiPasswordTextBox.OnCreateAutomationPeer() -> Microsoft.UI.Xaml.Automation.Peers.AutomationPeer!
static Microsoft.Maui.LifecycleEvents.WindowsLifecycleBuilderExtensions.OnAppInstanceActivated(this Microsoft.Maui.LifecycleEvents.IWindowsLifecycleBuilder! lifecycle, Microsoft.Maui.LifecycleEvents.WindowsLifecycle.OnAppInstanceActivated! del) -> Microsoft.Maui.LifecycleEvents.IWindowsLifecycleBuilder!
virtual Microsoft.Maui.LifecycleEvents.WindowsLifecycle.OnAppInstanceActivated.Invoke(Microsoft.UI.Xaml.Application! application, Microsoft.Windows.AppLifecycle.AppActivationArguments! args) -> bool
virtual Microsoft.Maui.MauiWinUIApplication.OnAppInstanceActivated(Microsoft.Windows.AppLifecycle.AppActivationArguments! args) -> bool
4 changes: 3 additions & 1 deletion src/Core/tests/DeviceTests.Shared/MauiProgramDefaults.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static MauiApp CreateMauiApp(List<Assembly> testAssemblies)
});
}

public static MauiApp CreateMauiApp(Func<IServiceProvider, TestOptions> options)
public static MauiApp CreateMauiApp(Func<IServiceProvider, TestOptions> options, Action<MauiAppBuilder> configureBuilder = null)

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

configureBuilder is declared as a non-nullable Action<MauiAppBuilder> but defaults to null. With nullable annotations enabled in the repo this will produce a nullability warning (and can become a build break when warnings are treated as errors). Make the parameter nullable (e.g., Action<MauiAppBuilder>? configureBuilder = null).

Suggested change
public static MauiApp CreateMauiApp(Func<IServiceProvider, TestOptions> options, Action<MauiAppBuilder> configureBuilder = null)
public static MauiApp CreateMauiApp(Func<IServiceProvider, TestOptions> options, Action<MauiAppBuilder>? configureBuilder = null)

Copilot uses AI. Check for mistakes.
{
var appBuilder = MauiApp.CreateBuilder();

Expand Down Expand Up @@ -95,6 +95,8 @@ public static MauiApp CreateMauiApp(Func<IServiceProvider, TestOptions> options)
ValidateScopes = true,
}));

configureBuilder?.Invoke(appBuilder);

var mauiApp = appBuilder.Build();

DefaultTestApp = mauiApp.Services.GetRequiredService<IApplication>();
Expand Down
43 changes: 43 additions & 0 deletions src/Core/tests/DeviceTests/LifecycleEventOrderTests.Android.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using System.Linq;
using Microsoft.Maui.LifecycleEvents;
using Xunit;

namespace Microsoft.Maui.DeviceTests
{
[Category(TestCategory.Lifecycle)]
public class LifecycleEventOrderTests
{
[Fact(DisplayName = "Android lifecycle events fire during startup")]
public void AndroidLifecycleEventsFireDuringStartup()
{
var log = MauiProgram.LifecycleEventLog;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[major] Device test reliability - These Android tests read LifecycleEventLog immediately, but OnStart/OnResume can be delivered after the test runner starts. That makes the assertions race startup lifecycle delivery and can fail with missing OnStart/OnResume. Please wait for Android startup to reach OnResume (or expose a startup-complete signal) before asserting the log/order.


Assert.Contains(nameof(AndroidLifecycle.OnCreate), log);
Assert.Contains(nameof(AndroidLifecycle.OnStart), log);
Assert.Contains(nameof(AndroidLifecycle.OnResume), log);
}

[Fact(DisplayName = "Android lifecycle events fire in correct order")]
public void AndroidLifecycleEventsFireInCorrectOrder()
{
var log = MauiProgram.LifecycleEventLog;

var createIndex = log.IndexOf(nameof(AndroidLifecycle.OnCreate));
var startIndex = log.IndexOf(nameof(AndroidLifecycle.OnStart));
var resumeIndex = log.IndexOf(nameof(AndroidLifecycle.OnResume));

// Expected startup order: OnCreate → OnStart → OnResume
Assert.True(createIndex < startIndex,
$"Expected OnCreate before OnStart. Log: [{string.Join(", ", log)}]");
Assert.True(startIndex < resumeIndex,
$"Expected OnStart before OnResume. Log: [{string.Join(", ", log)}]");
}

[Fact(DisplayName = "OnCreate fires exactly once during startup")]
public void OnCreateFiresExactlyOnce()
{
var count = MauiProgram.LifecycleEventLog.Count(e => e == nameof(AndroidLifecycle.OnCreate));
Assert.Equal(1, count);
}
}
}
47 changes: 47 additions & 0 deletions src/Core/tests/DeviceTests/LifecycleEventOrderTests.Windows.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using System.Linq;
using Microsoft.Maui.LifecycleEvents;
using Xunit;

namespace Microsoft.Maui.DeviceTests
{
[Category(TestCategory.Lifecycle)]
public class LifecycleEventOrderTests
{
[Fact(DisplayName = "Windows lifecycle events fire during startup")]
public void WindowsLifecycleEventsFireDuringStartup()
{
var log = MauiProgram.LifecycleEventLog;

Assert.Contains(nameof(WindowsLifecycle.OnAppInstanceActivated), log);
Assert.Contains(nameof(WindowsLifecycle.OnLaunching), log);
Assert.Contains(nameof(WindowsLifecycle.OnLaunched), log);
Assert.Contains(nameof(WindowsLifecycle.OnWindowCreated), log);
}

[Fact(DisplayName = "Windows lifecycle events fire in correct order")]
public void WindowsLifecycleEventsFireInCorrectOrder()
{
var log = MauiProgram.LifecycleEventLog;

var activatedIndex = log.IndexOf(nameof(WindowsLifecycle.OnAppInstanceActivated));
var launchingIndex = log.IndexOf(nameof(WindowsLifecycle.OnLaunching));
var windowCreatedIndex = log.IndexOf(nameof(WindowsLifecycle.OnWindowCreated));
var launchedIndex = log.IndexOf(nameof(WindowsLifecycle.OnLaunched));

// Expected startup order: OnAppInstanceActivated → OnLaunching → OnWindowCreated → OnLaunched
Assert.True(activatedIndex < launchingIndex,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔍 AI-Generated Review (multi-model)

[moderate] Device test correctness — The order assertions compare raw IndexOf results without first asserting that each event was found. A missing early event produces -1, which can still satisfy the < comparisons (for example, missing OnAppInstanceActivated makes -1 < launchingIndex pass), so this test can report the startup ordering as correct while the ordered event is absent. Add explicit >= 0 assertions (as the iOS test does for FinishedLaunching) before comparing indices; the same pattern exists in LifecycleEventOrderTests.Android.cs.

$"Expected OnAppInstanceActivated before OnLaunching. Log: [{string.Join(", ", log)}]");
Comment on lines +32 to +34
Assert.True(launchingIndex < windowCreatedIndex,
$"Expected OnLaunching before OnWindowCreated. Log: [{string.Join(", ", log)}]");
Assert.True(windowCreatedIndex < launchedIndex,
$"Expected OnWindowCreated before OnLaunched. Log: [{string.Join(", ", log)}]");
}

[Fact(DisplayName = "OnAppInstanceActivated fires exactly once during startup")]
public void OnAppInstanceActivatedFiresExactlyOnce()
{
var count = MauiProgram.LifecycleEventLog.Count(e => e == nameof(WindowsLifecycle.OnAppInstanceActivated));
Assert.Equal(1, count);
}
Comment on lines +51 to +56
}
}
41 changes: 41 additions & 0 deletions src/Core/tests/DeviceTests/LifecycleEventOrderTests.iOS.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System.Linq;
using Microsoft.Maui.LifecycleEvents;
using Xunit;

namespace Microsoft.Maui.DeviceTests
{
[Category(TestCategory.Lifecycle)]
public class LifecycleEventOrderTests
{
[Fact(DisplayName = "iOS lifecycle events fire during startup")]
public void iOSLifecycleEventsFireDuringStartup()
{
var log = MauiProgram.LifecycleEventLog;

Assert.Contains(nameof(iOSLifecycle.FinishedLaunching), log);
}

[Fact(DisplayName = "FinishedLaunching fires before OnActivated")]
public void FinishedLaunchingFiresBeforeOnActivated()
{
var log = MauiProgram.LifecycleEventLog;

var launchIndex = log.IndexOf(nameof(iOSLifecycle.FinishedLaunching));
Assert.True(launchIndex >= 0, "FinishedLaunching should have fired");

var activatedIndex = log.IndexOf(nameof(iOSLifecycle.OnActivated));
if (activatedIndex >= 0)
{
Assert.True(launchIndex < activatedIndex,
$"Expected FinishedLaunching before OnActivated. Log: [{string.Join(", ", log)}]");
}
}

[Fact(DisplayName = "FinishedLaunching fires exactly once during startup")]
public void FinishedLaunchingFiresExactlyOnce()
{
var count = MauiProgram.LifecycleEventLog.Count(e => e == nameof(iOSLifecycle.FinishedLaunching));
Assert.Equal(1, count);
}
}
}
51 changes: 51 additions & 0 deletions src/Core/tests/DeviceTests/MauiProgram.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ public static class MauiProgram
public static UI.Xaml.Window DefaultWindow => MauiProgramDefaults.DefaultWindow;
#endif

/// <summary>
/// Records platform lifecycle event names in the order they fire during app startup.
/// Used by LifecycleEventOrderTests to validate event ordering.
/// </summary>
public static List<string> LifecycleEventLog { get; } = new();
Comment on lines +17 to +21

Copilot AI Apr 9, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LifecycleEventLog is static and never cleared. Since the new tests assert some events fire "exactly once", later activations/lifecycle events (or test host reuse) can make them flaky. Consider clearing the log at the start of CreateMauiApp() so each run starts from a known state.

Copilot uses AI. Check for mistakes.

Comment on lines +17 to +22
public static IApplication DefaultTestApp { get; private set; }

public static MauiApp CreateMauiApp() =>
Expand All @@ -29,6 +35,51 @@ public static MauiApp CreateMauiApp() =>
};

return options;
},
configureBuilder: builder =>
{
builder.ConfigureLifecycleEvents(life =>
{
#if ANDROID
life.AddAndroid(android =>
{
android.OnCreate((a, b) =>
LifecycleEventLog.Add(nameof(AndroidLifecycle.OnCreate)));
android.OnStart(a =>
LifecycleEventLog.Add(nameof(AndroidLifecycle.OnStart)));
android.OnResume(a =>
LifecycleEventLog.Add(nameof(AndroidLifecycle.OnResume)));
android.OnPostResume(a =>
LifecycleEventLog.Add(nameof(AndroidLifecycle.OnPostResume)));
});
#elif IOS || MACCATALYST
life.AddiOS(ios =>
{
ios.FinishedLaunching((app, options) =>
{
LifecycleEventLog.Add(nameof(iOSLifecycle.FinishedLaunching));
return true;
});
ios.OnActivated(app =>
LifecycleEventLog.Add(nameof(iOSLifecycle.OnActivated)));
});
#elif WINDOWS
life.AddWindows(windows =>
{
windows.OnAppInstanceActivated((app, args) =>
{
LifecycleEventLog.Add(nameof(WindowsLifecycle.OnAppInstanceActivated));
return false;
});
windows.OnLaunching((app, args) =>
LifecycleEventLog.Add(nameof(WindowsLifecycle.OnLaunching)));
windows.OnLaunched((app, args) =>
LifecycleEventLog.Add(nameof(WindowsLifecycle.OnLaunched)));
windows.OnWindowCreated(w =>
LifecycleEventLog.Add(nameof(WindowsLifecycle.OnWindowCreated)));
});
#endif
});
});
}
}
1 change: 1 addition & 0 deletions src/Core/tests/DeviceTests/TestCategory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,6 @@ public static class TestCategory
public const string View = "View";
public const string WebView = "WebView";
public const string Window = "Window";
public const string Lifecycle = "Lifecycle";
}
}
Loading