[Windows] Lifecycle: Add app activation event - #34870
Conversation
|
🚀 Dogfood this PR with:
curl -fsSL https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.sh | bash -s -- 34870Or
iex "& { $(irm https://raw.githubusercontent.com/dotnet/maui/main/eng/scripts/get-maui-pr.ps1) } 34870" |
There was a problem hiding this comment.
Pull request overview
Adds a Windows lifecycle event hook for rich app activation (AppActivationArguments) so apps can handle initial and redirected activations (protocol/file/single-instance redirection) in a consistent way via lifecycle events, and updates the Controls sample to demonstrate single-instance redirection + activation logging. This PR also includes repo-wide dependency-flow/tooling updates (SDK/Arcade/Helix, Xcode requirement, feeds, etc.).
Changes:
- Add
WindowsLifecycle.OnAppActivation+ builder extension, and wire activation dispatching intoMauiWinUIApplication(initial activation + redirected activations). - Update Controls.Sample (Windows) to use a custom
Program.Mainfor single-instance redirection and to log the activation kind via the new lifecycle hook. - Update tooling/dependencies/CI configuration (global.json/Versions.props/Version.Details.xml/NuGet feeds/pool and Xcode settings) and adjust some tests accordingly.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Workload/workloads.csproj | Updates workload project TFM to net10.0. |
| src/TestUtils/src/Microsoft.Maui.IntegrationTests/WindowsTemplateTest.cs | Disables DotNetPrevious test cases (with TODO). |
| src/TestUtils/src/Microsoft.Maui.IntegrationTests/SimpleTemplateTest.cs | Disables DotNetPrevious test cases (with TODO). |
| src/TestUtils/src/Microsoft.Maui.IntegrationTests/AndroidTemplateTests.cs | Disables DotNetPrevious test cases (with TODO). |
| src/Templates/src/cgmanifest.json | Updates template cgmanifest package versions. |
| src/Core/tests/UnitTests/LifecycleEvents/LifecycleEventsTests.cs | Adds unit test verifying Windows OnAppActivation lifecycle registration/invocation. |
| src/Core/src/PublicAPI/net-windows/PublicAPI.Unshipped.txt | Declares new public API surface for Windows activation lifecycle hook. |
| src/Core/src/Platform/Windows/MauiWinUIApplication.cs | Dispatches rich activation args through lifecycle events (initial + redirected activations). |
| src/Core/src/LifecycleEvents/Windows/WindowsLifecycleBuilderExtensions.cs | Adds OnAppActivation(...) lifecycle builder extension method. |
| src/Core/src/LifecycleEvents/Windows/WindowsLifecycle.cs | Adds WindowsLifecycle.OnAppActivation delegate. |
| src/Controls/samples/Controls.Sample/Platforms/Windows/Program.cs | Adds custom Windows entry point demonstrating single-instance redirection. |
| src/Controls/samples/Controls.Sample/MauiProgram.cs | Hooks sample logging to WindowsLifecycle.OnAppActivation. |
| src/Controls/samples/Controls.Sample/Maui.Controls.Sample.csproj | Defines DISABLE_XAML_GENERATED_MAIN for Windows to support custom entry point. |
| src/BlazorWebView/tests/DeviceTests/Elements/BlazorWebViewTests.RequestInterception.cs | Skips a flaky theory due to external dependency. |
| NuGet.config | Updates/expands package sources (dependency-flow + manual feeds). |
| global.json | Updates .NET SDK tooling and Arcade/Helix SDK versions. |
| eng/Versions.props | Updates repo versioning (ci label, runtime/extensions versions, Android/macios package versions). |
| eng/Version.Details.xml | Updates dependency flow versions/shas for SDK/runtime/android/macios/extensions/arcade toolset. |
| eng/pipelines/common/variables.yml | Updates required Xcode version to 26.2.0. |
| eng/pipelines/ci.yml | Updates macOS pool selection/conditions to accommodate Xcode 26.2 availability constraints. |
| eng/common/tools.ps1 | Adjusts web requests and VS requirement probing logic in tooling script. |
| eng/common/templates/variables/pool-providers.yml | Updates documented Windows image override reference. |
| eng/common/post-build/nuget-verification.ps1 | Adjusts Invoke-WebRequest usage for nuget.exe download. |
| eng/common/internal-feed-operations.ps1 | Adjusts Invoke-WebRequest usage for cred provider bootstrap script. |
| eng/common/cross/x86/tizen/tizen.patch | Adds patch for Tizen cross toolchain libc linker script. |
| eng/common/cross/x64/tizen/tizen.patch | Adds patch for Tizen cross toolchain libc linker script. |
| eng/common/cross/arm64/tizen/tizen.patch | Adds patch for Tizen cross toolchain libc linker script. |
| eng/common/cross/arm/tizen/tizen.patch | Adds patch for Tizen cross toolchain libc linker script. |
| eng/common/core-templates/post-build/post-build.yml | Updates publishing pool image/demands from vs2019 to vs2022. |
| eng/common/core-templates/job/publish-build-assets.yml | Updates publishing pool image from vs2019 to vs2022. |
bee11cc to
9562b93
Compare
🧪 PR Test EvaluationOverall Verdict: The unit test correctly covers the happy path (multi-handler registration, both handlers invoked,
📊 Expand Full EvaluationPR Test Evaluation ReportPR: #34870 — [Windows] Add app activation lifecycle event Overall VerdictThe unit test is well-structured and consistent with the existing suite, but it only covers the "at least one handler returns 1. Fix Coverage —
|
🧪 PR Test EvaluationOverall Verdict: The PR adds a correct unit test for lifecycle event registration and invocation, but misses several edge cases for the
📊 Expand Full EvaluationPR Test Evaluation ReportPR: #34870 — [Windows] Add app activation lifecycle event Overall VerdictThe unit test verifies lifecycle event registration and invocation, but important edge cases around the 1. Fix Coverage —
|
🧪 PR Test EvaluationOverall Verdict: The lifecycle registration is well-tested, but the application-level integration in
📊 Expand Full EvaluationPR Test Evaluation ReportPR: #34870 — [Windows] Add app activation lifecycle event Overall VerdictThe unit test covers the lifecycle service registration layer well (event registration, multi-handler invocation, return-value OR logic), but the behavioral logic added to 1. Fix Coverage —
|
| Assertion | Quality | Notes |
|---|---|---|
Assert.True(service.ContainsEvent(...)) |
✅ Specific | Confirms registration |
Assert.True(firstHandlerCalled) |
✅ Specific | Both handlers invoked |
Assert.True(secondHandlerCalled) |
✅ Specific | Both handlers invoked |
Assert.True(wasHandled) |
✅ Specific | Return value OR logic |
All assertions are meaningful and specific to the behavior being tested.
9. Fix-Test Alignment — ⚠️ Partial mismatch
The test aligns with WindowsLifecycle.cs and WindowsLifecycleBuilderExtensions.cs (the lifecycle service API). It does not align with the changes in MauiWinUIApplication.cs, which represent the largest and most consequential portion of the fix. The actual integration — "when activation is handled, don't create the window" — is untested.
Recommendations
-
Add a test for the skip-window-creation behavior: Create a unit test (or device test) that verifies when an
OnAppActivationhandler returnstrue,MauiWinUIApplicationdoes not proceed toCreatePlatformWindow. This is the most important missing coverage. A subclass approach overridingOnAppActivationcould work without needing to mock native Windows APIs. -
Add a test for "no handlers returns false": Add a test case with zero
OnAppActivationhandlers registered to confirmOnAppActivationreturnsfalse(and window creation proceeds normally). This is the most common path (most apps won't use this event). -
Add a test for the late-launch path: Add a test that exercises the
_application != nullbranch (subsequent activation), verifying thatOnAppActivationis invoked butOnLaunchedis NOT re-fired.
Warning
⚠️ Firewall blocked 1 domain
The following domain was blocked by the firewall during workflow execution:
dc.services.visualstudio.com
To allow these domains, add them to the network.allowed list in your workflow frontmatter:
network:
allowed:
- defaults
- "dc.services.visualstudio.com"See Network Configuration for more information.
Note
🔒 Integrity filtering filtered 1 item
Integrity filtering activated and filtered the following item during workflow execution.
This happens when a tool call accesses a resource that does not meet the required integrity or secrecy level of the workflow.
- pr:[Windows] Lifecycle: Add app activation event #34870 (
pull_request_read: Resource 'pr:[Windows] Lifecycle: Add app activation event #34870' has lower integrity than agent requires. Agent would need to drop integrity tags [unapproved:all approved:all] to trust this resource.)
🧪 Test evaluation by Evaluate PR Tests
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
103e600 to
14d3233
Compare
|
Superseded by #34883 to restart review on a clean thread. |
Note
Are you waiting for the changes in this PR to be merged?
It would be very helpful if you could test the resulting artifacts from this PR and let us know in a comment if this change resolves your issue. Thank you!
Root Cause
On Windows, MAUI exposed launch and window lifecycle hooks but not the underlying
AppActivationArgumentspayload. That made single-instance redirect, protocol or file activation, and follow-on Windows auth work harder to handle cleanly fromMauiProgramwithout app-specific plumbing.Description of Change
This PR adds a new Windows lifecycle hook:
WindowsLifecycle.OnAppActivation(UI.Xaml.Application, AppActivationArguments) -> boolIWindowsLifecycleBuilder.OnAppActivation(...)MauiWinUIApplicationnow:AppInstance.GetActivatedEventArgs()payload,AppInstance.GetCurrent().Activated,The Controls sample demonstrates using this from
MauiProgramto keep the app single-instanced, redirect later launches back into the running instance, and re-activate the existing MAUI window. The redirected losing instance follows the WinAppSDK single-instance pattern and terminates immediately afterRedirectActivationToAsync(...).Key Technical Details
_services = applicationContext.Servicesso lifecycle handlers can actually run.OnAppActivationhook.AppInstance.Activatedis only subscribed once.What NOT to Do (for future agents)
_servicesexists - it becomes a no-op because the lifecycle pipeline has not been built yet.MauiWinUIApplication- this PR intentionally keeps the API generic.Program.csjust to observe app activation in a MAUI app - the goal here is a reusable lifecycle event fromMauiProgram.Issues Fixed
Related to #9973
Testing
dotnet build src\Controls\samples\Controls.Sample\Maui.Controls.Sample.csproj -f net10.0-windows10.0.20348.0 /p:RestoreIgnoreFailedSources=true /p:NuGetAudit=false /p:WarningsNotAsErrors=NU1301;NU1801 /p:TreatWarningsAsErrors=falsedotnet test src\Core\tests\UnitTests\Core.UnitTests.csproj --filter LifecycleEventsTests /p:RestoreIgnoreFailedSources=true /p:NuGetAudit=false /p:WarningsNotAsErrors=NU1301;NU1801 /p:TreatWarningsAsErrors=false