Skip to content

Fix NullReferenceException crash when launching UWP apps from PowerToys Run#47376

Closed
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-powertoys-camera-crash
Closed

Fix NullReferenceException crash when launching UWP apps from PowerToys Run#47376
Copilot wants to merge 3 commits into
mainfrom
copilot/fix-powertoys-camera-crash

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 29, 2026

Summary of the Pull Request

Fixes a crash in PowerToys Run's UWP launcher where a NullReferenceException escapes an error-handling catch block inside an async void method, causing an unhandled exception on the WPF dispatcher. The crash was reported when launching Camera via PT Run but affects any UWP app whose launch fails.

PR Checklist

  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized
  • Dev docs: Added/updated
  • New binaries: Added on the required places
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

Root cause — two-stage failure:

  1. ActivateApplication(UserModelId, ...) fails (e.g. UserModelId is null/empty for certain apps).
  2. The catch block calls ProgramLogger.Exception(..., MethodBase.GetCurrentMethod().DeclaringType, ...). Inside a Task.Run lambda in .NET 9, MethodBase.GetCurrentMethod() can return null, so .DeclaringType throws a secondary NullReferenceException that escapes the catch block entirely.

Because Launch is async void, the uncaught exception propagates to the WPF dispatcher and crashes the process. The same .NET 9 / MethodBase.GetCurrentMethod() issue was already identified and fixed in PluginManager.cs (lines 242–245) with an explicit comment.

Changes in UWPApplication.cs:

  • Replace MethodBase.GetCurrentMethod().DeclaringTypeGetType() in the Launch lambda catch block. GetType() is always non-null on any instance and is the correct fix, consistent with PluginManager.cs.
  • Same replacement in IfApplicationCanRunElevated()'s catch block for consistency.
  • Add an explicit string.IsNullOrEmpty(UserModelId) guard before calling ActivateApplication — logs the anomaly and shows a graceful user-facing error instead of propagating into the COM call.
  • Use api?.ShowMsg() (null-conditional) for additional defensive robustness.
// Before — secondary NullReferenceException escapes catch in .NET 9
catch (Exception ex)
{
    ProgramLogger.Exception($"Unable to launch UWP {DisplayName}", ex,
        MethodBase.GetCurrentMethod().DeclaringType, queryArguments);  // boom
    api.ShowMsg(...);
}

// After
if (string.IsNullOrEmpty(UserModelId))
{
    ProgramLogger.Exception($"UserModelId is null or empty for {DisplayName}",
        new InvalidOperationException(), GetType(), queryArguments);
    api?.ShowMsg(...);
    return;
}
appManager.ActivateApplication(UserModelId, queryArguments, noFlags, out var unusedPid);
...
catch (Exception ex)
{
    ProgramLogger.Exception($"Unable to launch UWP {DisplayName}", ex, GetType(), queryArguments);
    api?.ShowMsg(...);
}

Regression test added in UWPTests.cs:

  • UwpResultActionShouldHandleEmptyUserModelIdGracefully constructs a UWPApplication with UserModelId = string.Empty, invokes the result action, and asserts that ShowMsg is called with the display name in the message — without throwing or crashing the async void path. A ManualResetEventSlim is used to properly synchronize with the async launch operation.

Validation Steps Performed

  • Code review confirmed the MethodBase.GetCurrentMethod() / .NET 9 regression is the same root cause documented in PluginManager.cs.
  • Manual inspection of the stack trace from the issue report matches exactly: NullReferenceException originating at the top of the lambda (b__0) rather than inside a nested callee, consistent with the .DeclaringType access on a null MethodBase being the throw site.
  • Regression test UwpResultActionShouldHandleEmptyUserModelIdGracefully added and verified passing locally (96 tests passing in Microsoft.Plugin.Program.UnitTests).

…odBase.GetCurrentMethod().DeclaringType with GetType() and adding null guard for UserModelId

Agent-Logs-Url: https://github.com/microsoft/PowerToys/sessions/30311995-2a99-4433-8115-d805ec66b678

Co-authored-by: MuyuanMS <116717757+MuyuanMS@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix PowerToys crash when launching camera due to NullReferenceException Fix NullReferenceException crash when launching UWP apps from PowerToys Run Apr 29, 2026
Copilot AI requested a review from MuyuanMS April 29, 2026 10:14
@niels9001 niels9001 added the Product-PowerToys Run Improved app launch PT Run (Win+R) Window label Apr 29, 2026
@MuyuanMS MuyuanMS requested a review from Copilot May 14, 2026 03:10
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes a PowerToys Run UWP launch crash by making UWP launch failure logging avoid MethodBase.GetCurrentMethod() in affected async/error paths and by handling missing app user model IDs gracefully.

Changes:

  • Adds a null/empty UserModelId guard before UWP activation.
  • Replaces vulnerable MethodBase.GetCurrentMethod().DeclaringType logging calls with GetType().
  • Makes launch failure message display null-safe via api?.ShowMsg().

Comment on lines +214 to +220
if (string.IsNullOrEmpty(UserModelId))
{
ProgramLogger.Exception($"UserModelId is null or empty for {DisplayName}", new InvalidOperationException(), GetType(), queryArguments);
var name = "Plugin: " + Properties.Resources.wox_plugin_program_plugin_name;
var message = $"{Properties.Resources.powertoys_run_plugin_program_uwp_failed}: {DisplayName}";
api?.ShowMsg(name, message, string.Empty);
return;
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Added a regression test in src/modules/launcher/Plugins/Microsoft.Plugin.Program.UnitTests/Programs/UWPTests.cs that exercises launching a UWPApplication with an empty UserModelId.

The test verifies the result action returns successfully and reports the launch failure through ShowMsg instead of throwing. I also rebuilt Microsoft.Plugin.Program and Microsoft.Plugin.Program.UnitTests, then ran the full Microsoft.Plugin.Program.UnitTests assembly locally (96 passing).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@MuyuanMS
Copy link
Copy Markdown
Contributor

@copilot please re-review the latest changes.

Copy link
Copy Markdown
Contributor Author

Copilot AI commented May 14, 2026

@copilot please re-review the latest changes.

The changes look good. The regression test in commit 6af94d0 correctly exercises the empty UserModelId guard path:

  • Constructs a UWPApplication with UserModelId = string.Empty
  • Uses ManualResetEventSlim to properly synchronize with the async void launch, ensuring ShowMsg is awaited before asserting
  • Verifies ShowMsg is called exactly once with the display name in the message
  • Confirms the action returns true without throwing any exception

The fix in UWPApplication.cs (commit 1311ae8) is also correct — GetType() is always non-null on any instance and is consistent with the same fix already applied in PluginManager.cs. The CI checks (Dependency Review, Spell checking) pass on the latest commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Product-PowerToys Run Improved app launch PT Run (Win+R) Window

Projects

None yet

Development

Successfully merging this pull request may close these issues.

PowerToys Crash when launching camera NullReferenceException for RunFromThreadPoolDispatchLoop

4 participants