Fix the WinGet missing / Admin crash (#38493)

This is a fix for a pair of related crashes. 

Basically, we'd crash on startup if we failed to initialize WinGet. This could happen in two different places:
* If WinGet wasn't installed, then we'd explode, cause obviously we can't call its APIs
* If we're running as Admin, we won't be able to instantiate it's COM server. 

Regardless of how it happens, I've defaulted us to just _not enabling the winget built-in_. That's the simplest solution here. 

As I was helpfully reminded, there's also an elevated WindowsPackageManagerFactory we could use too - though, that wouldn't solve the case of "winget isn't installed"

Closes #38460
Closes #38440 (most likely)
This commit is contained in:
Mike Griese
2025-04-08 06:22:29 -05:00
committed by GitHub
parent 9e8754a592
commit d7e826d2ac
3 changed files with 28 additions and 8 deletions

View File

@@ -2,6 +2,7 @@
// The Microsoft Corporation licenses this file to you under the MIT license. // The Microsoft Corporation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using ManagedCommon;
using Microsoft.CmdPal.Common.Helpers; using Microsoft.CmdPal.Common.Helpers;
using Microsoft.CmdPal.Common.Services; using Microsoft.CmdPal.Common.Services;
using Microsoft.CmdPal.Ext.Apps; using Microsoft.CmdPal.Ext.Apps;
@@ -78,7 +79,7 @@ public partial class App : Application
var cmdArgs = Environment.GetCommandLineArgs(); var cmdArgs = Environment.GetCommandLineArgs();
bool runFromPT = false; var runFromPT = false;
foreach (var arg in cmdArgs) foreach (var arg in cmdArgs)
{ {
if (arg == "RunFromPT") if (arg == "RunFromPT")
@@ -107,9 +108,6 @@ public partial class App : Application
// Built-in Commands. Order matters - this is the order they'll be presented by default. // Built-in Commands. Order matters - this is the order they'll be presented by default.
var allApps = new AllAppsCommandProvider(); var allApps = new AllAppsCommandProvider();
var winget = new WinGetExtensionCommandsProvider();
var callback = allApps.LookupApp;
winget.SetAllLookup(callback);
services.AddSingleton<ICommandProvider>(allApps); services.AddSingleton<ICommandProvider>(allApps);
services.AddSingleton<ICommandProvider, ShellCommandsProvider>(); services.AddSingleton<ICommandProvider, ShellCommandsProvider>();
services.AddSingleton<ICommandProvider, CalculatorCommandProvider>(); services.AddSingleton<ICommandProvider, CalculatorCommandProvider>();
@@ -120,7 +118,25 @@ public partial class App : Application
// services.AddSingleton<ICommandProvider, ClipboardHistoryCommandsProvider>(); // services.AddSingleton<ICommandProvider, ClipboardHistoryCommandsProvider>();
services.AddSingleton<ICommandProvider, WindowWalkerCommandsProvider>(); services.AddSingleton<ICommandProvider, WindowWalkerCommandsProvider>();
services.AddSingleton<ICommandProvider, WebSearchCommandsProvider>(); services.AddSingleton<ICommandProvider, WebSearchCommandsProvider>();
services.AddSingleton<ICommandProvider>(winget);
// GH #38440: Users might not have WinGet installed! Or they might have
// a ridiculously old version. Or might be running as admin.
// We shouldn't explode in the App ctor if we fail to instantiate an
// instance of PackageManager, which will happen in the static ctor
// for WinGetStatics
try
{
var winget = new WinGetExtensionCommandsProvider();
var callback = allApps.LookupApp;
winget.SetAllLookup(callback);
services.AddSingleton<ICommandProvider>(winget);
}
catch (Exception ex)
{
Logger.LogError("Couldn't load winget");
Logger.LogError(ex.ToString());
}
services.AddSingleton<ICommandProvider, WindowsTerminalCommandsProvider>(); services.AddSingleton<ICommandProvider, WindowsTerminalCommandsProvider>();
services.AddSingleton<ICommandProvider, WindowsSettingsCommandsProvider>(); services.AddSingleton<ICommandProvider, WindowsSettingsCommandsProvider>();
services.AddSingleton<ICommandProvider, RegistryCommandsProvider>(); services.AddSingleton<ICommandProvider, RegistryCommandsProvider>();

View File

@@ -189,7 +189,7 @@ public partial class InstallPackageListItem : ListItem
private void InstallStateChangedHandler(object? sender, InstallPackageCommand e) private void InstallStateChangedHandler(object? sender, InstallPackageCommand e)
{ {
if (!ApiInformation.IsApiContractPresent("Microsoft.Management.Deployment", 12)) if (!ApiInformation.IsApiContractPresent("Microsoft.Management.Deployment.WindowsPackageManagerContract", 12))
{ {
Logger.LogError($"RefreshPackageCatalogAsync isn't available"); Logger.LogError($"RefreshPackageCatalogAsync isn't available");
e.FakeChangeStatus(); e.FakeChangeStatus();

View File

@@ -12,6 +12,7 @@ using System.Threading.Tasks;
using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit; using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Management.Deployment; using Microsoft.Management.Deployment;
using Windows.Foundation.Metadata;
using WindowsPackageManager.Interop; using WindowsPackageManager.Interop;
namespace Microsoft.CmdPal.Ext.WinGet; namespace Microsoft.CmdPal.Ext.WinGet;
@@ -51,9 +52,12 @@ internal static class WinGetStatics
_storeCatalog, _storeCatalog,
]; ];
foreach (var catalogReference in AvailableCatalogs) if (ApiInformation.IsApiContractPresent("Microsoft.Management.Deployment.WindowsPackageManagerContract", 8))
{ {
catalogReference.PackageCatalogBackgroundUpdateInterval = new(0); foreach (var catalogReference in AvailableCatalogs)
{
catalogReference.PackageCatalogBackgroundUpdateInterval = new(0);
}
} }
// Immediately start the lazy-init of the all packages catalog, but // Immediately start the lazy-init of the all packages catalog, but