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.
// See the LICENSE file in the project root for more information.
using ManagedCommon;
using Microsoft.CmdPal.Common.Helpers;
using Microsoft.CmdPal.Common.Services;
using Microsoft.CmdPal.Ext.Apps;
@@ -78,7 +79,7 @@ public partial class App : Application
var cmdArgs = Environment.GetCommandLineArgs();
bool runFromPT = false;
var runFromPT = false;
foreach (var arg in cmdArgs)
{
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.
var allApps = new AllAppsCommandProvider();
var winget = new WinGetExtensionCommandsProvider();
var callback = allApps.LookupApp;
winget.SetAllLookup(callback);
services.AddSingleton<ICommandProvider>(allApps);
services.AddSingleton<ICommandProvider, ShellCommandsProvider>();
services.AddSingleton<ICommandProvider, CalculatorCommandProvider>();
@@ -120,7 +118,25 @@ public partial class App : Application
// services.AddSingleton<ICommandProvider, ClipboardHistoryCommandsProvider>();
services.AddSingleton<ICommandProvider, WindowWalkerCommandsProvider>();
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, WindowsSettingsCommandsProvider>();
services.AddSingleton<ICommandProvider, RegistryCommandsProvider>();

View File

@@ -189,7 +189,7 @@ public partial class InstallPackageListItem : ListItem
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");
e.FakeChangeStatus();

View File

@@ -12,6 +12,7 @@ using System.Threading.Tasks;
using Microsoft.CommandPalette.Extensions;
using Microsoft.CommandPalette.Extensions.Toolkit;
using Microsoft.Management.Deployment;
using Windows.Foundation.Metadata;
using WindowsPackageManager.Interop;
namespace Microsoft.CmdPal.Ext.WinGet;
@@ -51,9 +52,12 @@ internal static class WinGetStatics
_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