Issues with COM API and retrieving installed packages
Brief description of your issue
I have been trying to implement native WinGet support (WinGet COM API) on a NET/C# App (WingetUI), and I am experiencing issues when fetching installed packages. More specifically, WinGet does not identify which packages are available on WinGet repositories, and all of the packages are listed as local only.
Running winget list shows the correct package sources on the right of package (nothing is shown if package is local, winget or msstore otherwhise).
Note: Packages do load and the list of installed packages is correct; and searching on remote catalogs works flawlessly.
Steps to reproduce
- Clone the repository https://github.com/marticliment/WinGet-API-from-CSharp and open the solution.
- On demo console app, replace Program.cs file contents by the following:
using Microsoft.Management.Deployment;
using System.Security.Principal;
using Windows.ApplicationModel;
// Include WinGet Namespace
using WindowsPackageManager.Interop;
namespace WingetTest
{
internal class Program
{
static public void Main(string[] args)
{
var WinGetFactory = new WindowsPackageManagerStandardFactory();
var WinGetManager = WinGetFactory.CreatePackageManager();
// Tested all of them, none of them worked
PackageCatalogReference selectedRemoteCatalogRef = WinGetManager.GetPackageCatalogByName("winget");
// PackageCatalogReference selectedRemoteCatalogRef = WinGetManager.GetPackageCatalogByName("msstore");
// PackageCatalogReference selectedRemoteCatalogRef = WinGetManager.GetLocalPackageCatalog(LocalPackageCatalog.InstalledPackages);
// PackageCatalogReference selectedRemoteCatalogRef = WinGetManager.GetPredefinedPackageCatalog(PredefinedPackageCatalog.OpenWindowsCatalog);
// PackageCatalogReference selectedRemoteCatalogRef = WinGetManager.GetPredefinedPackageCatalog(PredefinedPackageCatalog.MicrosoftStore);
// PackageCatalogReference selectedRemoteCatalogRef = WinGetManager.GetPredefinedPackageCatalog(PredefinedPackageCatalog.DesktopFrameworks);
CreateCompositePackageCatalogOptions createCompositePackageCatalogOptions = WinGetFactory.CreateCreateCompositePackageCatalogOptions();
createCompositePackageCatalogOptions.Catalogs.Append(selectedRemoteCatalogRef);
createCompositePackageCatalogOptions.CompositeSearchBehavior = CompositeSearchBehavior.LocalCatalogs;
var LocalCatalogRef = WinGetManager.CreateCompositePackageCatalog(createCompositePackageCatalogOptions);
var ConnectResult = LocalCatalogRef.Connect();
if (ConnectResult.Status != ConnectResultStatus.Ok)
{
throw new Exception("WinGet: Failed to connect to local catalog.");
}
FindPackagesOptions findPackagesOptions = WinGetFactory.CreateFindPackagesOptions();
PackageMatchFilter filter = WinGetFactory.CreatePackageMatchFilter();
filter.Field = PackageMatchField.Id;
filter.Option = PackageFieldMatchOption.Equals;
filter.Value = "";
findPackagesOptions.Filters.Append(filter);
var TaskResult = ConnectResult.PackageCatalog.FindPackages(findPackagesOptions);
foreach (var match in TaskResult.Matches.ToArray())
{
if (match.CatalogPackage.DefaultInstallVersion != null)
Console.WriteLine("Package is available Online: " + match.CatalogPackage.DefaultInstallVersion.PackageCatalog.Info.Name);
else
Console.WriteLine("Package is local only: " + match.CatalogPackage.Id);
}
}
}
}
Expected behavior
WinGet identifying the online packages as such when loading a local composite catalog, so they have a valid DefaultInstallVersion and online information can be retieved (update date, origin, newer versions, etc.)
Actual behavior
WinGet does not detect online packages as such. IDs are not reported properly and packages do have a null DefaultInstallVersion property.
Interestingly, the same code works flawlessly on a WinRT/C++ environment (this is from SampleWinGetCaller, tested and working flawlessly):
int32_t selectedIndex = catalogsListBox().SelectedIndex();
co_await winrt::resume_background();
PackageManager packageManager = CreatePackageManager();
PackageCatalogReference installedSearchCatalogRef{ nullptr };
// PackageCatalogReference selectedRemoteCatalogRef = packageManager.GetPackageCatalogs().GetAt(0); //msstore
PackageCatalogReference selectedRemoteCatalogRef = packageManager.GetPackageCatalogs().GetAt(1); //winget
CreateCompositePackageCatalogOptions createCompositePackageCatalogOptions = CreateCreateCompositePackageCatalogOptions();
createCompositePackageCatalogOptions.Catalogs().Append(selectedRemoteCatalogRef);
createCompositePackageCatalogOptions.CompositeSearchBehavior(CompositeSearchBehavior::LocalCatalogs);
installedSearchCatalogRef = packageManager.CreateCompositePackageCatalog(createCompositePackageCatalogOptions);
ConnectResult connectResult{ co_await installedSearchCatalogRef.ConnectAsync() };
PackageCatalog installedCatalog = connectResult.PackageCatalog();
if (!installedCatalog)
{
// Connect Error.
co_await winrt::resume_foreground(statusText.Dispatcher());
statusText.Text(L"Failed to connect to catalog.");
co_return;
}
FindPackagesOptions findPackagesOptions = CreateFindPackagesOptions();
auto value = m_installAppId;
FindPackagesResult findResult{ TryFindPackageInCatalogAsync(installedCatalog, m_installAppId).get() };
auto matches = findResult.Matches();
co_await winrt::resume_foreground(statusText.Dispatcher());
m_installedPackages.Clear();
for (auto const match : matches)
{
// Filter to only packages that match the selectedCatalogRef
auto version = match.CatalogPackage().DefaultInstallVersion();
if (selectedIndex < 0 || (version && version.PackageCatalog().Info().Id() == m_packageCatalogs.GetAt(selectedIndex).Info().Id()))
{
m_installedPackages.Append(match.CatalogPackage());
}
}
statusText.Text(L"");
Environment
OS:
- Windows 11 10.0.22635.3350
Tested .NET versions:
- NET6.0
- NET8.0
Tested WinGet versions:
- 1.7.10661
- 1.8.xxxxx-preview
Tested `Microsoft.WindowsPackageManager.ComInterop` versions:
- 1.7.10091-preview
- 1.5.1572
- 1.4.10052
Microsoft.Management.Deployment.WINMD files provided on:
- Microsoft.WindowsPackageManager.ComInterop package (all versions above)
- The latest WinGet release (extracted from the MSIX installer)
- The WinMD used by SampleWinGetCaller
All of the combinations above do behave as detailed above.
Hi I'm an AI powered bot that finds similar issues based off the issue title.
Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!
Open similar issues:
- Multiple installed versions of .NET Desktop Runtime are incorrectly matched when running
winget upgrade. (#4158), similarity score: 0.77
Closed similar issues:
- WinGetUI not displaying updates or installed packages but winget cli works (#3908), similarity score: 0.75
Note: You can give me feedback by thumbs upping or thumbs downing this comment.
@marticliment if you debug, you will see the problem:
its not added to the composit catalog option sadly. BUT it is because you use "append" instead of "add". Add adds the catalog to the composite options. But i tested, does not change anything. Still i get packages shown which are not from the "winget" catalog , but have a empty source. We need a working --source winget option for the COM API
As of version 1.8.1791, this code seems to be working. Thanks @PatrickSchmidtSE for pointing into the right direction
// var WinGetFactory = new WindowsPackageManagerElevatedFactory();
var WinGetFactory = new WindowsPackageManagerStandardFactory();
var WinGetManager = WinGetFactory.CreatePackageManager();
// CHANGE THIS INDEX
int selectedIndex = 0;
PackageCatalogReference installedSearchCatalogRef;
if (selectedIndex < 0)
{
installedSearchCatalogRef = WinGetManager.GetLocalPackageCatalog(LocalPackageCatalog.InstalledPackages);
}
else
{
PackageCatalogReference selectedRemoteCatalogRef = WinGetManager.GetPackageCatalogs().ToArray().ElementAt(selectedIndex);
Console.WriteLine($"Searching on package catalog {selectedRemoteCatalogRef.Info.Name} ");
CreateCompositePackageCatalogOptions createCompositePackageCatalogOptions = WinGetFactory.CreateCreateCompositePackageCatalogOptions();
createCompositePackageCatalogOptions.Catalogs.Add(selectedRemoteCatalogRef);
createCompositePackageCatalogOptions.CompositeSearchBehavior = CompositeSearchBehavior.LocalCatalogs;
installedSearchCatalogRef = WinGetManager.CreateCompositePackageCatalog(createCompositePackageCatalogOptions);
}
var ConnectResult = installedSearchCatalogRef.Connect();
if (ConnectResult.Status != ConnectResultStatus.Ok)
{
throw new Exception("WinGet: Failed to connect to local catalog.");
}
FindPackagesOptions findPackagesOptions = WinGetFactory.CreateFindPackagesOptions();
PackageMatchFilter filter = WinGetFactory.CreatePackageMatchFilter();
filter.Field = PackageMatchField.Id;
filter.Option = PackageFieldMatchOption.ContainsCaseInsensitive;
filter.Value = "";
findPackagesOptions.Filters.Add(filter);
var TaskResult = ConnectResult.PackageCatalog.FindPackages(findPackagesOptions);
Console.WriteLine("Begin enumeration");
foreach (var match in TaskResult.Matches.ToArray())
{
if (match.CatalogPackage.DefaultInstallVersion != null)
Console.WriteLine($"Package {match.CatalogPackage.Name} is available Online: " + match.CatalogPackage.DefaultInstallVersion.PackageCatalog.Info.Name);
//else
//Console.WriteLine("Package is local only: " + match.CatalogPackage.Id);
}
Console.WriteLine("End enumeration");