diff --git a/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj b/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj
index 2112c9731..8c72c09d0 100644
--- a/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj
+++ b/src/UniGetUI.Core.Classes.Tests/UniGetUI.Core.Classes.Tests.csproj
@@ -32,11 +32,14 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj b/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj
index 40e7ba506..a3c44ed60 100644
--- a/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj
+++ b/src/UniGetUI.Core.Data.Tests/UniGetUI.Core.Data.Tests.csproj
@@ -33,10 +33,13 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj b/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj
index c57c5ebbb..a1b45886e 100644
--- a/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj
+++ b/src/UniGetUI.Core.IconEngine.Tests/UniGetUI.Core.IconEngine.Tests.csproj
@@ -33,10 +33,13 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj b/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj
index 73cfcf9a7..b2cfe2ccd 100644
--- a/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj
+++ b/src/UniGetUI.Core.Language.Tests/UniGetUI.Core.LanguageEngine.Tests.csproj
@@ -33,10 +33,13 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj b/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj
index 42e4db33e..627a1a4b8 100644
--- a/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj
+++ b/src/UniGetUI.Core.Logging.Tests/UniGetUI.Core.Logging.Tests.csproj
@@ -33,10 +33,13 @@
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
-
-
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj b/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj
index e2ad5a4d3..6a8eae4e3 100644
--- a/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj
+++ b/src/UniGetUI.Core.Settings.Tests/UniGetUI.Core.Settings.Tests.csproj
@@ -30,9 +30,12 @@
-
-
-
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj b/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj
index 3ab53cd19..3de765a84 100644
--- a/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj
+++ b/src/UniGetUI.Core.Tools.Tests/UniGetUI.Core.Tools.Tests.csproj
@@ -30,9 +30,12 @@
-
-
-
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs
index 660e0501c..48fa01c8b 100644
--- a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGet.cs
@@ -113,201 +113,20 @@ public WinGet() : base()
protected override async Task FindPackages_UnSafe(string query)
{
- return await WinGetHelper.Instance.FindPackages_UnSafe(this, query);
+ return await Task.Run(() => WinGetHelper.Instance.FindPackages_UnSafe(this, query).GetAwaiter().GetResult());
}
-
+
protected override async Task GetAvailableUpdates_UnSafe()
{
- if (Settings.Get("ForceLegacyBundledWinGet"))
- return await BundledWinGetLegacyMethods.GetAvailableUpdates_UnSafe(this);
-
- List Packages = [];
-
- Process p = new()
- {
- StartInfo = new ProcessStartInfo()
- {
- FileName = "cmd.exe",
- Arguments = "/C " + PowerShellPath + " " + PowerShellPromptArgs,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- CreateNoWindow = true,
- StandardOutputEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
- StandardInputEncoding = new UTF8Encoding(false),
- StandardErrorEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
- }
- };
-
- ManagerClasses.Classes.ProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.ListUpdates, p);
-
- p.Start();
-
- string command = """
- Write-Output (Get-Module -Name Microsoft.WinGet.Client).Version
- Import-Module Microsoft.WinGet.Client
- function Print-WinGetPackage {
- param (
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name,
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Id,
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $InstalledVersion,
- [Parameter(ValueFromPipelineByPropertyName)] [string[]] $AvailableVersions,
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [bool] $IsUpdateAvailable,
- [Parameter(ValueFromPipelineByPropertyName)] [string] $Source
- )
- process {
- if($IsUpdateAvailable)
- {
- Write-Output("#" + $Name + "`t" + $Id + "`t" + $InstalledVersion + "`t" + $AvailableVersions[0] + "`t" + $Source)
- }
- }
- }
-
- Get-WinGetPackage | Print-WinGetPackage
-
- exit
-
- """;
-
- await p.StandardInput.WriteAsync(command);
- p.StandardInput.Close();
- logger.AddToStdIn(command);
-
- string? line;
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- logger.AddToStdOut(line);
- if (!line.StartsWith("#"))
- {
- continue; // The PowerShell script appends a '#' to the beginning of each line to identify the output
- }
-
- string[] elements = line.Split('\t');
- if (elements.Length < 5)
- {
- continue;
- }
-
- ManagerSource source = GetSourceOrDefault(elements[4]);
-
- Packages.Add(new Package(elements[0][1..], elements[1], elements[2], elements[3], source, this));
- }
-
- logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
- await p.WaitForExitAsync();
- logger.Close(p.ExitCode);
-
- if (Packages.Count() > 0)
- {
- return Packages.ToArray();
- }
- else
- {
- Logger.Warn("WinGet updates returned zero packages, attempting legacy...");
- return await BundledWinGetLegacyMethods.GetAvailableUpdates_UnSafe(this);
- }
+ return await Task.Run(() => WinGetHelper.Instance.GetAvailableUpdates_UnSafe(this).GetAwaiter().GetResult());
}
-
+
protected override async Task GetInstalledPackages_UnSafe()
{
- if (Settings.Get("ForceLegacyBundledWinGet"))
- return await BundledWinGetLegacyMethods.GetInstalledPackages_UnSafe(this);
-
- List Packages = [];
- Process p = new()
- {
- StartInfo = new ProcessStartInfo()
- {
- FileName = "cmd.exe",
- Arguments = "/C " + PowerShellPath + " " + PowerShellPromptArgs,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- CreateNoWindow = true,
- StandardOutputEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
- StandardInputEncoding = new UTF8Encoding(false),
- StandardErrorEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
- }
- };
-
- ManagerClasses.Classes.ProcessTaskLogger logger = TaskLogger.CreateNew(LoggableTaskType.ListInstalledPackages, p);
- p.Start();
-
- string command = """
- Write-Output (Get-Module -Name Microsoft.WinGet.Client).Version
- Import-Module Microsoft.WinGet.Client
- function Print-WinGetPackage {
- param (
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name,
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Id,
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $InstalledVersion,
- [Parameter(ValueFromPipelineByPropertyName)] [string[]] $AvailableVersions,
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [bool] $IsUpdateAvailable,
- [Parameter(ValueFromPipelineByPropertyName)] [string] $Source
- )
- process {
- Write-Output("#" + $Name + "`t" + $Id + "`t" + $InstalledVersion + "`t" + $Source)
- }
- }
-
- Get-WinGetPackage | Print-WinGetPackage
-
-
- exit
-
- """;
-
- await p.StandardInput.WriteAsync(command);
- p.StandardInput.Close();
- logger.AddToStdIn(command);
-
-
- string? line;
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- logger.AddToStdOut(line);
- if (!line.StartsWith("#"))
- {
- continue; // The PowerShell script appends a '#' to the beginning of each line to identify the output
- }
-
- string[] elements = line.Split('\t');
- if (elements.Length < 4)
- {
- continue;
- }
-
- ManagerSource source;
- if (elements[3] != "")
- {
- source = GetSourceOrDefault(elements[3]);
- }
- else
- {
- source = GetLocalSource(elements[1]);
- }
-
- Packages.Add(new Package(elements[0][1..], elements[1], elements[2], source, this));
- }
-
- logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
- await p.WaitForExitAsync();
- logger.Close(p.ExitCode);
-
- if (Packages.Count() > 0)
- {
- return Packages.ToArray();
- }
- else
- {
- Logger.Warn("WinGet installed packages returned zero packages, attempting legacy...");
- return await BundledWinGetLegacyMethods.GetInstalledPackages_UnSafe(this);
- }
+ return await Task.Run(() => WinGetHelper.Instance.GetInstalledPackages_UnSafe(this).GetAwaiter().GetResult());
}
-
- private ManagerSource GetLocalSource(string id)
+
+ public ManagerSource GetLocalSource(string id)
{
try
{
@@ -361,6 +180,7 @@ private ManagerSource GetLocalSource(string id)
return LocalPcSource;
}
}
+
public override string[] GetInstallParameters(Package package, InstallationOptions options)
{
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers.cs
deleted file mode 100644
index fe6cad8bd..000000000
--- a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers.cs
+++ /dev/null
@@ -1,846 +0,0 @@
-using Microsoft.Management.Deployment;
-using System.Diagnostics;
-using System.Text;
-using System.Text.RegularExpressions;
-using UniGetUI.Core.Data;
-using UniGetUI.Core.Logging;
-using UniGetUI.Core.SettingsEngine;
-using UniGetUI.Core.Tools;
-using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
-using UniGetUI.PackageEngine.Enums;
-using UniGetUI.PackageEngine.PackageClasses;
-using WindowsPackageManager.Interop;
-
-namespace UniGetUI.PackageEngine.Managers.WingetManager
-{
- internal static class WinGetHelper
- {
- private static IWinGetPackageHelper? __helper;
- public static IWinGetPackageHelper Instance
- {
- get
- {
- if (__helper == null)
- {
- __helper = new BundledWinGetHelper();
- }
- return __helper;
- }
-
- set
- {
- __helper = value;
- }
- }
- }
-
- internal interface IWinGetPackageHelper
- {
-
- public Task FindPackages_UnSafe(WinGet ManagerInstance, string query);
- public Task GetSources_UnSafe(WinGet ManagerInstance);
- public Task GetPackageVersions_Unsafe(WinGet ManagerInstance, Package package);
- public Task GetPackageDetails_UnSafe(WinGet ManagerInstance, PackageDetails details);
-
- }
-
- internal class NativeWinGetHelper : IWinGetPackageHelper
- {
- public WindowsPackageManagerStandardFactory Factory;
- public PackageManager WinGetManager;
-
- public NativeWinGetHelper()
- {
- if (CoreTools.IsAdministrator())
- {
- Logger.Info("Running elevated, WinGet class registration is likely to fail");
- }
-
- Factory = new WindowsPackageManagerStandardFactory();
- WinGetManager = Factory.CreatePackageManager();
- }
-
-
- public async Task FindPackages_UnSafe(WinGet ManagerInstance, string query)
- {
- List Packages = [];
- ManagerClasses.Classes.NativeTaskLogger logger = ManagerInstance.TaskLogger.CreateNew(LoggableTaskType.FindPackages);
- foreach (string query_part in query.Replace(".", " ").Split(" "))
- {
- FindPackagesOptions PackageFilters = Factory.CreateFindPackagesOptions();
-
- logger.Log("Generating filters...");
- // Name filter
- PackageMatchFilter FilterName = Factory.CreatePackageMatchFilter();
- FilterName.Field = PackageMatchField.Name;
- FilterName.Value = query_part;
- FilterName.Option = PackageFieldMatchOption.ContainsCaseInsensitive;
- PackageFilters.Filters.Add(FilterName);
-
- // Id filter
- PackageMatchFilter FilterId = Factory.CreatePackageMatchFilter();
- FilterId.Field = PackageMatchField.Id;
- FilterId.Value = query_part;
- FilterId.Option = PackageFieldMatchOption.ContainsCaseInsensitive;
- PackageFilters.Filters.Add(FilterId);
-
- // Load catalogs
- logger.Log("Loading available catalogs...");
- IReadOnlyList AvailableCatalogs = WinGetManager.GetPackageCatalogs();
- Dictionary> FindPackageTasks = [];
-
- // Spawn Tasks to find packages on catalogs
- logger.Log("Spawning catalog fetching tasks...");
- foreach (PackageCatalogReference CatalogReference in AvailableCatalogs.ToArray())
- {
- logger.Log($"Begin search on catalog {CatalogReference.Info.Name}");
- // Connect to catalog
- CatalogReference.AcceptSourceAgreements = true;
- ConnectResult result = await CatalogReference.ConnectAsync();
- if (result.Status == ConnectResultStatus.Ok)
- {
- try
- {
- // Create task and spawn it
- Task task = new(() => result.PackageCatalog.FindPackages(PackageFilters));
- task.Start();
-
- // Add task to list
- FindPackageTasks.Add(
- CatalogReference,
- task
- );
- }
- catch (Exception e)
- {
- logger.Error("WinGet: Catalog " + CatalogReference.Info.Name + " failed to spawn FindPackages task.");
- logger.Error(e);
- }
- }
- else
- {
- logger.Error("WinGet: Catalog " + CatalogReference.Info.Name + " failed to connect.");
- }
- }
-
- // Wait for tasks completion
- await Task.WhenAll(FindPackageTasks.Values.ToArray());
- logger.Log($"All catalogs fetched. Fetching results for query piece {query_part}");
-
- foreach (KeyValuePair> CatalogTaskPair in FindPackageTasks)
- {
- try
- {
- // Get the source for the catalog
- ManagerSource source = ManagerInstance.GetSourceOrDefault(CatalogTaskPair.Key.Info.Name);
-
- FindPackagesResult FoundPackages = CatalogTaskPair.Value.Result;
- foreach (MatchResult package in FoundPackages.Matches.ToArray())
- {
- CatalogPackage catPkg = package.CatalogPackage;
- // Create the Package item and add it to the list
- logger.Log($"Found package: {catPkg.Name}|{catPkg.Id}|{catPkg.DefaultInstallVersion.Version} on catalog {source.Name}");
- Packages.Add(new Package(
- catPkg.Name,
- catPkg.Id,
- catPkg.DefaultInstallVersion.Version,
- source,
- ManagerInstance
- ));
- }
- }
- catch (Exception e)
- {
- logger.Error("WinGet: Catalog " + CatalogTaskPair.Key.Info.Name + " failed to get available packages.");
- logger.Error(e);
- }
- }
- }
- logger.Close(0);
- return Packages.ToArray();
- }
-
- public async Task GetSources_UnSafe(WinGet ManagerInstance)
- {
- List sources = [];
- ManagerClasses.Classes.NativeTaskLogger logger = ManagerInstance.TaskLogger.CreateNew(LoggableTaskType.ListSources);
-
- foreach (PackageCatalogReference catalog in await Task.Run(() => WinGetManager.GetPackageCatalogs().ToArray()))
- {
- try
- {
- logger.Log($"Found source {catalog.Info.Name} with argument {catalog.Info.Argument}");
- sources.Add(new ManagerSource(ManagerInstance, catalog.Info.Name, new Uri(catalog.Info.Argument), updateDate: catalog.Info.LastUpdateTime.ToString()));
- }
- catch (Exception e)
- {
- logger.Error(e);
- }
- }
-
- logger.Close(0);
- return sources.ToArray();
- }
-
- public async Task GetPackageVersions_Unsafe(WinGet ManagerInstance, Package package)
- {
- ManagerClasses.Classes.NativeTaskLogger logger = ManagerInstance.TaskLogger.CreateNew(LoggableTaskType.LoadPackageVersions);
-
- // Find the native package for the given Package object
- PackageCatalogReference Catalog = WinGetManager.GetPackageCatalogByName(package.Source.Name);
- if (Catalog == null)
- {
- logger.Error("Failed to get catalog " + package.Source.Name + ". Is the package local?");
- logger.Close(1);
- return [];
- }
-
- // Connect to catalog
- Catalog.AcceptSourceAgreements = true;
- ConnectResult ConnectResult = await Task.Run(() => Catalog.Connect());
- if (ConnectResult.Status != ConnectResultStatus.Ok)
- {
- logger.Error("Failed to connect to catalog " + package.Source.Name);
- logger.Close(1);
- return [];
- }
-
- // Match only the exact same Id
- FindPackagesOptions packageMatchFilter = Factory.CreateFindPackagesOptions();
- PackageMatchFilter filters = Factory.CreatePackageMatchFilter();
- filters.Field = PackageMatchField.Id;
- filters.Value = package.Id;
- filters.Option = PackageFieldMatchOption.Equals;
- packageMatchFilter.Filters.Add(filters);
- packageMatchFilter.ResultLimit = 1;
- Task SearchResult = Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
-
- if (SearchResult.Result == null || SearchResult.Result.Matches == null || SearchResult.Result.Matches.Count() == 0)
- {
- logger.Error("Failed to find package " + package.Id + " in catalog " + package.Source.Name);
- logger.Close(1);
- return [];
- }
-
- // Get the Native Package
- CatalogPackage NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
- string[] versions = NativePackage.AvailableVersions.Select(x => x.Version).ToArray();
- foreach (string? version in versions)
- {
- logger.Log(version);
- }
-
- logger.Close(0);
- return versions ?? [];
- }
-
- public async Task GetPackageDetails_UnSafe(WinGet ManagerInstance, PackageDetails details)
- {
- ManagerClasses.Classes.NativeTaskLogger logger = ManagerInstance.TaskLogger.CreateNew(LoggableTaskType.LoadPackageDetails);
-
- if (details.Package.Source.Name == "winget")
- {
- details.ManifestUrl = new Uri("https://github.com/microsoft/winget-pkgs/tree/master/manifests/"
- + details.Package.Id[0].ToString().ToLower() + "/"
- + details.Package.Id.Split('.')[0] + "/"
- + String.Join("/", details.Package.Id.Contains('.') ? details.Package.Id.Split('.')[1..] : details.Package.Id.Split('.'))
- );
- }
- else if (details.Package.Source.Name == "msstore")
- {
- details.ManifestUrl = new Uri("https://apps.microsoft.com/detail/" + details.Package.Id);
- }
-
- // Find the native package for the given Package object
- PackageCatalogReference Catalog = WinGetManager.GetPackageCatalogByName(details.Package.Source.Name);
- if (Catalog == null)
- {
- logger.Error("Failed to get catalog " + details.Package.Source.Name + ". Is the package local?");
- logger.Close(1);
- return;
- }
-
- // Connect to catalog
- Catalog.AcceptSourceAgreements = true;
- ConnectResult ConnectResult = await Task.Run(() => Catalog.Connect());
- if (ConnectResult.Status != ConnectResultStatus.Ok)
- {
- logger.Error("Failed to connect to catalog " + details.Package.Source.Name);
- logger.Close(1);
- return;
- }
-
- // Match only the exact same Id
- FindPackagesOptions packageMatchFilter = Factory.CreateFindPackagesOptions();
- PackageMatchFilter filters = Factory.CreatePackageMatchFilter();
- filters.Field = PackageMatchField.Id;
- filters.Value = details.Package.Id;
- filters.Option = PackageFieldMatchOption.Equals;
- packageMatchFilter.Filters.Add(filters);
- packageMatchFilter.ResultLimit = 1;
- Task SearchResult = Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
-
- if (SearchResult.Result == null || SearchResult.Result.Matches == null || SearchResult.Result.Matches.Count() == 0)
- {
- logger.Error("WinGet: Failed to find package " + details.Package.Id + " in catalog " + details.Package.Source.Name);
- logger.Close(1);
- return;
- }
-
- // Get the Native Package
- CatalogPackage NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
-
- // Extract data from NativeDetails
- CatalogPackageMetadata NativeDetails = NativePackage.DefaultInstallVersion.GetCatalogPackageMetadata(Windows.System.UserProfile.GlobalizationPreferences.Languages[0]);
-
- if (NativeDetails.Author != "")
- {
- details.Author = NativeDetails.Author;
- }
-
- if (NativeDetails.Description != "")
- {
- details.Description = NativeDetails.Description;
- }
-
- if (NativeDetails.PackageUrl != "")
- {
- details.HomepageUrl = new Uri(NativeDetails.PackageUrl);
- }
-
- if (NativeDetails.License != "")
- {
- details.License = NativeDetails.License;
- }
-
- if (NativeDetails.LicenseUrl != "")
- {
- details.LicenseUrl = new Uri(NativeDetails.LicenseUrl);
- }
-
- if (NativeDetails.Publisher != "")
- {
- details.Publisher = NativeDetails.Publisher;
- }
-
- if (NativeDetails.ReleaseNotes != "")
- {
- details.ReleaseNotes = NativeDetails.ReleaseNotes;
- }
-
- if (NativeDetails.ReleaseNotesUrl != "")
- {
- details.ReleaseNotesUrl = new Uri(NativeDetails.ReleaseNotesUrl);
- }
-
- if (NativeDetails.Tags != null)
- {
- details.Tags = NativeDetails.Tags.ToArray();
- }
-
-
- // There is no way yet to retrieve installer URLs right now so this part will be console-parsed.
- // TODO: Replace this code with native code when available on the COM api
- Process process = new();
- List output = [];
- ProcessStartInfo startInfo = new()
- {
- FileName = ManagerInstance.WinGetBundledPath,
- Arguments = ManagerInstance.Properties.ExecutableCallArgs + " show --id " + details.Package.Id + " --exact --disable-interactivity --accept-source-agreements --source " + details.Package.Source.Name,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
- };
- process.StartInfo = startInfo;
- process.Start();
-
- logger.Log("Begin loading installers:");
- logger.Log(" Executable: " + startInfo.FileName);
- logger.Log(" Arguments: " + startInfo.Arguments);
-
- // Retrieve the output
- string? _line;
- while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
- {
- if (_line.Trim() != "")
- {
- logger.Log(_line);
- output.Add(_line);
- }
- }
-
- logger.Error(await process.StandardError.ReadToEndAsync());
-
- // Parse the output
- foreach (string __line in output)
- {
- try
- {
- string line = __line.Trim();
- if (line.Contains("Installer SHA256:"))
- {
- details.InstallerHash = line.Split(":")[1].Trim();
- }
- else if (line.Contains("Installer Url:"))
- {
- details.InstallerUrl = new Uri(line.Replace("Installer Url:", "").Trim());
- details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
- }
- else if (line.Contains("Release Date:"))
- {
- details.UpdateDate = line.Split(":")[1].Trim();
- }
- else if (line.Contains("Installer Type:"))
- {
- details.InstallerType = line.Split(":")[1].Trim();
- }
- }
- catch (Exception e)
- {
- Logger.Warn("Error occurred while parsing line value=\"" + __line + "\"");
- Logger.Warn(e.Message);
- }
- }
- logger.Close(0);
- return;
- }
- }
-
-
- internal class BundledWinGetHelper : IWinGetPackageHelper
- {
-
- public BundledWinGetHelper()
- {
-
- }
-
- public async Task FindPackages_UnSafe(WinGet ManagerInstance, string query)
- {
- if (Settings.Get("ForceLegacyBundledWinGet"))
- return await BundledWinGetLegacyMethods.FindPackages_UnSafe(ManagerInstance, query);
-
- List Packages = [];
-
- Process p = new()
- {
- StartInfo = new ProcessStartInfo()
- {
- FileName = "cmd.exe",
- Arguments = "/C " + ManagerInstance.PowerShellPath + " " + ManagerInstance.PowerShellPromptArgs,
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- CreateNoWindow = true,
- StandardOutputEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
- StandardInputEncoding = new UTF8Encoding(false),
- StandardErrorEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
- }
- };
-
- p.Start();
-
- ManagerClasses.Classes.ProcessTaskLogger logger = ManagerInstance.TaskLogger.CreateNew(LoggableTaskType.FindPackages, p);
-
- string command = """
- Write-Output (Get-Module -Name Microsoft.WinGet.Client).Version
- Import-Module Microsoft.WinGet.Client
- function Print-WinGetPackage {
- param (
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name,
- [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Id,
- [Parameter(ValueFromPipelineByPropertyName)] [string[]] $AvailableVersions,
- [Parameter(ValueFromPipelineByPropertyName)] [string] $Source
- )
- process {
- Write-Output(""#"" + $Name + ""`t"" + $Id + ""`t"" + $AvailableVersions[0] + ""`t"" + $Source)
- }
- }
-
- Find-WinGetPackage -Query {query} | Print-WinGetPackage
-
- exit
-
-
- """;
-
- await p.StandardInput.WriteAsync(command);
- p.StandardInput.Close();
- logger.AddToStdIn(command);
-
- string? line;
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- logger.AddToStdOut(line);
- if (!line.StartsWith("#"))
- {
- continue; // The PowerShell script appends a '#' to the beginning of each line to identify the output
- }
-
- string[] elements = line.Split('\t');
- if (elements.Length < 4)
- {
- continue;
- }
-
- ManagerSource source = ManagerInstance.GetSourceOrDefault(elements[3]);
-
- Packages.Add(new Package(elements[0][1..], elements[1], elements[2], source, ManagerInstance));
- }
-
- logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
- await p.WaitForExitAsync();
- logger.Close(p.ExitCode);
-
- if (Packages.Count() > 0)
- {
- return Packages.ToArray();
- }
- else
- {
- Logger.Warn("WinGet package fetching returned zero packages, attempting legacy...");
- return await BundledWinGetLegacyMethods.FindPackages_UnSafe(ManagerInstance, query);
- }
-
- }
-
- public async Task GetPackageDetails_UnSafe(WinGet ManagerInstance, PackageDetails details)
- {
- if (details.Package.Source.Name == "winget")
- {
- details.ManifestUrl = new Uri("https://github.com/microsoft/winget-pkgs/tree/master/manifests/"
- + details.Package.Id[0].ToString().ToLower() + "/"
- + details.Package.Id.Split('.')[0] + "/"
- + String.Join("/", details.Package.Id.Contains('.') ? details.Package.Id.Split('.')[1..] : details.Package.Id.Split('.'))
- );
- }
- else if (details.Package.Source.Name == "msstore")
- {
- details.ManifestUrl = new Uri("https://apps.microsoft.com/detail/" + details.Package.Id);
- }
-
- // Get the output for the best matching locale
- Process process = new();
- string packageIdentifier = "--id " + details.Package.Id + " --exact";
-
- List output = [];
- bool LocaleFound = true;
- ProcessStartInfo startInfo = new()
- {
- FileName = ManagerInstance.WinGetBundledPath,
- Arguments = ManagerInstance.Properties.ExecutableCallArgs + " show " + packageIdentifier + " --disable-interactivity --accept-source-agreements --locale " + System.Globalization.CultureInfo.CurrentCulture.ToString(),
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
- };
- process.StartInfo = startInfo;
- process.Start();
-
- string? _line;
- while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
- {
- if (_line.Trim() != "")
- {
- output.Add(_line);
- if (_line.Contains("The value provided for the `locale` argument is invalid") || _line.Contains("No applicable installer found; see Logger.Logs for more details."))
- {
- LocaleFound = false;
- break;
- }
- }
- }
-
- // Load fallback english locale
- if (!LocaleFound)
- {
- output.Clear();
- Logger.Info("Winget could not found culture data for package Id=" + details.Package.Id + " and Culture=" + System.Globalization.CultureInfo.CurrentCulture.ToString() + ". Trying to get data for en-US");
- process = new Process();
- LocaleFound = true;
- startInfo = new()
- {
- FileName = ManagerInstance.WinGetBundledPath,
- Arguments = ManagerInstance.Properties.ExecutableCallArgs + " show " + packageIdentifier + " --disable-interactivity --accept-source-agreements --locale en-US",
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
- };
- process.StartInfo = startInfo;
- process.Start();
-
- while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
- {
- if (_line.Trim() != "")
- {
- output.Add(_line);
- if (_line.Contains("The value provided for the `locale` argument is invalid") || _line.Contains("No applicable installer found; see Logger.Logs for more details."))
- {
- LocaleFound = false;
- break;
- }
- }
- }
- }
-
- // Load default locale
- if (!LocaleFound)
- {
- output.Clear();
- Logger.Info("Winget could not found culture data for package Id=" + details.Package.Id + " and Culture=en-US. Loading default");
- LocaleFound = true;
- process = new Process();
- startInfo = new()
- {
- FileName = ManagerInstance.WinGetBundledPath,
- Arguments = ManagerInstance.Properties.ExecutableCallArgs + " show " + packageIdentifier + " --disable-interactivity --accept-source-agreements",
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
- };
- process.StartInfo = startInfo;
- process.Start();
-
- while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
- {
- if (_line.Trim() != "")
- {
- output.Add(_line);
- }
- }
- }
-
- // Parse the output
- bool IsLoadingDescription = false;
- bool IsLoadingReleaseNotes = false;
- bool IsLoadingTags = false;
- foreach (string __line in output)
- {
- try
- {
- string line = __line.TrimEnd();
- if (line == "")
- {
- continue;
- }
-
- // Check if a multiline field is being loaded
- if (line.StartsWith(" ") && IsLoadingDescription)
- {
- details.Description += "\n" + line.Trim();
- }
- else if (line.StartsWith(" ") && IsLoadingReleaseNotes)
- {
- details.ReleaseNotes += "\n" + line.Trim();
- }
- else if (line.StartsWith(" ") && IsLoadingTags)
- {
- details.Tags = details.Tags.Append(line.Trim()).ToArray();
- }
-
- // Stop loading multiline fields
- else if (IsLoadingDescription)
- {
- IsLoadingDescription = false;
- }
- else if (IsLoadingReleaseNotes)
- {
- IsLoadingReleaseNotes = false;
- }
- else if (IsLoadingTags)
- {
- IsLoadingTags = false;
- }
-
- // Check for singleline fields
- if (line.Contains("Publisher:"))
- {
- details.Publisher = line.Split(":")[1].Trim();
- }
- else if (line.Contains("Author:"))
- {
- details.Author = line.Split(":")[1].Trim();
- }
- else if (line.Contains("Homepage:"))
- {
- details.HomepageUrl = new Uri(line.Replace("Homepage:", "").Trim());
- }
- else if (line.Contains("License:"))
- {
- details.License = line.Split(":")[1].Trim();
- }
- else if (line.Contains("License Url:"))
- {
- details.LicenseUrl = new Uri(line.Replace("License Url:", "").Trim());
- }
- else if (line.Contains("Installer SHA256:"))
- {
- details.InstallerHash = line.Split(":")[1].Trim();
- }
- else if (line.Contains("Installer Url:"))
- {
- details.InstallerUrl = new Uri(line.Replace("Installer Url:", "").Trim());
- details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
- }
- else if (line.Contains("Release Date:"))
- {
- details.UpdateDate = line.Split(":")[1].Trim();
- }
- else if (line.Contains("Release Notes Url:"))
- {
- details.ReleaseNotesUrl = new Uri(line.Replace("Release Notes Url:", "").Trim());
- }
- else if (line.Contains("Installer Type:"))
- {
- details.InstallerType = line.Split(":")[1].Trim();
- }
- else if (line.Contains("Description:"))
- {
- details.Description = line.Split(":")[1].Trim();
- IsLoadingDescription = true;
- }
- else if (line.Contains("ReleaseNotes"))
- {
- details.ReleaseNotes = line.Split(":")[1].Trim();
- IsLoadingReleaseNotes = true;
- }
- else if (line.Contains("Tags"))
- {
- details.Tags = new string[0];
- IsLoadingTags = true;
- }
- }
- catch (Exception e)
- {
- Logger.Warn("Error occurred while parsing line value=\"" + _line + "\"");
- Logger.Warn(e.Message);
- }
- }
-
- return;
- }
-
- public async Task GetPackageVersions_Unsafe(WinGet ManagerInstance, Package package)
- {
- Process p = new()
- {
- StartInfo = new ProcessStartInfo()
- {
- FileName = ManagerInstance.WinGetBundledPath,
- Arguments = ManagerInstance.Properties.ExecutableCallArgs + " show --id " + package.Id + " --exact --versions --accept-source-agreements",
- UseShellExecute = false,
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
- }
- };
-
- ManagerClasses.Classes.ProcessTaskLogger logger = ManagerInstance.TaskLogger.CreateNew(LoggableTaskType.LoadPackageVersions, p);
-
- p.Start();
-
- string? line;
- List versions = [];
- bool DashesPassed = false;
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- logger.AddToStdOut(line);
- if (!DashesPassed)
- {
- if (line.Contains("---"))
- {
- DashesPassed = true;
- }
- }
- else
- {
- versions.Add(line.Trim());
- }
- }
- logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
- await p.WaitForExitAsync();
- logger.Close(p.ExitCode);
- return versions.ToArray();
- }
-
- public async Task GetSources_UnSafe(WinGet ManagerInstance)
- {
- List sources = [];
-
- Process p = new()
- {
- StartInfo = new()
- {
- FileName = ManagerInstance.Status.ExecutablePath,
- Arguments = ManagerInstance.Properties.ExecutableCallArgs + " source list",
- RedirectStandardOutput = true,
- RedirectStandardError = true,
- RedirectStandardInput = true,
- UseShellExecute = false,
- CreateNoWindow = true,
- StandardOutputEncoding = System.Text.Encoding.UTF8
- }
- };
-
- p.Start();
-
- ManagerClasses.Classes.ProcessTaskLogger logger = ManagerInstance.TaskLogger.CreateNew(LoggableTaskType.FindPackages, p);
-
- bool dashesPassed = false;
- string? line;
- while ((line = await p.StandardOutput.ReadLineAsync()) != null)
- {
- logger.AddToStdOut(line);
- try
- {
- if (string.IsNullOrEmpty(line))
- {
- continue;
- }
-
- if (!dashesPassed)
- {
- if (line.Contains("---"))
- {
- dashesPassed = true;
- }
- }
- else
- {
- string[] parts = Regex.Replace(line.Trim(), " {2,}", " ").Split(' ');
- if (parts.Length > 1)
- {
- sources.Add(new ManagerSource(ManagerInstance, parts[0].Trim(), new Uri(parts[1].Trim())));
- }
- }
- }
- catch (Exception e)
- {
- Logger.Warn(e);
- }
- }
-
- logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
- await p.WaitForExitAsync();
- logger.Close(p.ExitCode);
- return sources.ToArray();
-
- }
- }
-}
-
-
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/BundledWinGetHelper.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/BundledWinGetHelper.cs
new file mode 100644
index 000000000..8ef3624e6
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/BundledWinGetHelper.cs
@@ -0,0 +1,651 @@
+using System.Diagnostics;
+using System.Text;
+using System.Text.RegularExpressions;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.SettingsEngine;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.PackageClasses;
+
+namespace UniGetUI.PackageEngine.Managers.WingetManager;
+
+internal class BundledWinGetHelper : IWinGetManagerHelper
+{
+ public BundledWinGetHelper()
+ {
+ }
+
+ public async Task GetAvailableUpdates_UnSafe(WinGet Manager)
+ {
+ if (Settings.Get("ForceLegacyBundledWinGet"))
+ return await BundledWinGetLegacyMethods.GetAvailableUpdates_UnSafe(Manager);
+
+ List Packages = [];
+
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = "cmd.exe",
+ Arguments = "/C " + Manager.PowerShellPath + " " + Manager.PowerShellPromptArgs,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
+ StandardInputEncoding = new UTF8Encoding(false),
+ StandardErrorEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
+ }
+ };
+
+ ManagerClasses.Classes.ProcessTaskLogger logger = Manager.TaskLogger.CreateNew(LoggableTaskType.ListUpdates, p);
+
+ p.Start();
+
+ string command = """
+ Write-Output (Get-Module -Name Microsoft.WinGet.Client).Version
+ Import-Module Microsoft.WinGet.Client
+ function Print-WinGetPackage {
+ param (
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Id,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $InstalledVersion,
+ [Parameter(ValueFromPipelineByPropertyName)] [string[]] $AvailableVersions,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [bool] $IsUpdateAvailable,
+ [Parameter(ValueFromPipelineByPropertyName)] [string] $Source
+ )
+ process {
+ if($IsUpdateAvailable)
+ {
+ Write-Output("#" + $Name + "`t" + $Id + "`t" + $InstalledVersion + "`t" + $AvailableVersions[0] + "`t" + $Source)
+ }
+ }
+ }
+
+ Get-WinGetPackage | Print-WinGetPackage
+
+ exit
+
+ """;
+
+ await p.StandardInput.WriteAsync(command);
+ p.StandardInput.Close();
+ logger.AddToStdIn(command);
+
+ string? line;
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ logger.AddToStdOut(line);
+ if (!line.StartsWith("#"))
+ {
+ continue; // The PowerShell script appends a '#' to the beginning of each line to identify the output
+ }
+
+ string[] elements = line.Split('\t');
+ if (elements.Length < 5)
+ {
+ continue;
+ }
+
+ ManagerSource source = Manager.GetSourceOrDefault(elements[4]);
+
+ Packages.Add(new Package(elements[0][1..], elements[1], elements[2], elements[3], source, Manager));
+ }
+
+ logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
+ await p.WaitForExitAsync();
+ logger.Close(p.ExitCode);
+
+ if (Packages.Count() > 0)
+ {
+ return Packages.ToArray();
+ }
+ else
+ {
+ Logger.Warn("WinGet updates returned zero packages, attempting legacy...");
+ return await BundledWinGetLegacyMethods.GetAvailableUpdates_UnSafe(Manager);
+ }
+ }
+
+ public async Task GetInstalledPackages_UnSafe(WinGet Manager)
+ {
+ if (Settings.Get("ForceLegacyBundledWinGet"))
+ return await BundledWinGetLegacyMethods.GetInstalledPackages_UnSafe(Manager);
+
+ List Packages = [];
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = "cmd.exe",
+ Arguments = "/C " + Manager.PowerShellPath + " " + Manager.PowerShellPromptArgs,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
+ StandardInputEncoding = new UTF8Encoding(false),
+ StandardErrorEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
+ }
+ };
+
+ ManagerClasses.Classes.ProcessTaskLogger logger =
+ Manager.TaskLogger.CreateNew(LoggableTaskType.ListInstalledPackages, p);
+ p.Start();
+
+ string command = """
+ Write-Output (Get-Module -Name Microsoft.WinGet.Client).Version
+ Import-Module Microsoft.WinGet.Client
+ function Print-WinGetPackage {
+ param (
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Id,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $InstalledVersion,
+ [Parameter(ValueFromPipelineByPropertyName)] [string[]] $AvailableVersions,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [bool] $IsUpdateAvailable,
+ [Parameter(ValueFromPipelineByPropertyName)] [string] $Source
+ )
+ process {
+ Write-Output("#" + $Name + "`t" + $Id + "`t" + $InstalledVersion + "`t" + $Source)
+ }
+ }
+
+ Get-WinGetPackage | Print-WinGetPackage
+
+
+ exit
+
+ """;
+
+ await p.StandardInput.WriteAsync(command);
+ p.StandardInput.Close();
+ logger.AddToStdIn(command);
+
+
+ string? line;
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ logger.AddToStdOut(line);
+ if (!line.StartsWith("#"))
+ {
+ continue; // The PowerShell script appends a '#' to the beginning of each line to identify the output
+ }
+
+ string[] elements = line.Split('\t');
+ if (elements.Length < 4)
+ {
+ continue;
+ }
+
+ ManagerSource source;
+ if (elements[3] != "")
+ {
+ source = Manager.GetSourceOrDefault(elements[3]);
+ }
+ else
+ {
+ source = Manager.GetLocalSource(elements[1]);
+ }
+
+ Packages.Add(new Package(elements[0][1..], elements[1], elements[2], source, Manager));
+ }
+
+ logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
+ await p.WaitForExitAsync();
+ logger.Close(p.ExitCode);
+
+ if (Packages.Count() > 0)
+ {
+ return Packages.ToArray();
+ }
+ else
+ {
+ Logger.Warn("WinGet installed packages returned zero packages, attempting legacy...");
+ return await BundledWinGetLegacyMethods.GetInstalledPackages_UnSafe(Manager);
+ }
+ }
+
+
+ public async Task FindPackages_UnSafe(WinGet Manager, string query)
+ {
+ if (Settings.Get("ForceLegacyBundledWinGet"))
+ return await BundledWinGetLegacyMethods.FindPackages_UnSafe(Manager, query);
+
+ List Packages = [];
+
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = "cmd.exe",
+ Arguments = "/C " + Manager.PowerShellPath + " " + Manager.PowerShellPromptArgs,
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
+ StandardInputEncoding = new UTF8Encoding(false),
+ StandardErrorEncoding = CodePagesEncodingProvider.Instance.GetEncoding(CoreData.CODE_PAGE),
+ }
+ };
+
+ p.Start();
+
+ ManagerClasses.Classes.ProcessTaskLogger
+ logger = Manager.TaskLogger.CreateNew(LoggableTaskType.FindPackages, p);
+
+ string command = """
+ Write-Output (Get-Module -Name Microsoft.WinGet.Client).Version
+ Import-Module Microsoft.WinGet.Client
+ function Print-WinGetPackage {
+ param (
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Name,
+ [Parameter(Mandatory,ValueFromPipelineByPropertyName)] [string] $Id,
+ [Parameter(ValueFromPipelineByPropertyName)] [string[]] $AvailableVersions,
+ [Parameter(ValueFromPipelineByPropertyName)] [string] $Source
+ )
+ process {
+ Write-Output(""#"" + $Name + ""`t"" + $Id + ""`t"" + $AvailableVersions[0] + ""`t"" + $Source)
+ }
+ }
+
+ Find-WinGetPackage -Query {query} | Print-WinGetPackage
+
+ exit
+
+
+ """;
+
+ await p.StandardInput.WriteAsync(command);
+ p.StandardInput.Close();
+ logger.AddToStdIn(command);
+
+ string? line;
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ logger.AddToStdOut(line);
+ if (!line.StartsWith("#"))
+ {
+ continue; // The PowerShell script appends a '#' to the beginning of each line to identify the output
+ }
+
+ string[] elements = line.Split('\t');
+ if (elements.Length < 4)
+ {
+ continue;
+ }
+
+ ManagerSource source = Manager.GetSourceOrDefault(elements[3]);
+
+ Packages.Add(new Package(elements[0][1..], elements[1], elements[2], source, Manager));
+ }
+
+ logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
+ await p.WaitForExitAsync();
+ logger.Close(p.ExitCode);
+
+ if (Packages.Count() > 0)
+ {
+ return Packages.ToArray();
+ }
+ else
+ {
+ Logger.Warn("WinGet package fetching returned zero packages, attempting legacy...");
+ return await BundledWinGetLegacyMethods.FindPackages_UnSafe(Manager, query);
+ }
+
+ }
+
+ public async Task GetPackageDetails_UnSafe(WinGet Manager, PackageDetails details)
+ {
+ if (details.Package.Source.Name == "winget")
+ {
+ details.ManifestUrl = new Uri("https://github.com/microsoft/winget-pkgs/tree/master/manifests/"
+ + details.Package.Id[0].ToString().ToLower() + "/"
+ + details.Package.Id.Split('.')[0] + "/"
+ + String.Join("/",
+ details.Package.Id.Contains('.')
+ ? details.Package.Id.Split('.')[1..]
+ : details.Package.Id.Split('.'))
+ );
+ }
+ else if (details.Package.Source.Name == "msstore")
+ {
+ details.ManifestUrl = new Uri("https://apps.microsoft.com/detail/" + details.Package.Id);
+ }
+
+ // Get the output for the best matching locale
+ Process process = new();
+ string packageIdentifier = "--id " + details.Package.Id + " --exact";
+
+ List output = [];
+ bool LocaleFound = true;
+ ProcessStartInfo startInfo = new()
+ {
+ FileName = Manager.WinGetBundledPath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " show " + packageIdentifier +
+ " --disable-interactivity --accept-source-agreements --locale " +
+ System.Globalization.CultureInfo.CurrentCulture.ToString(),
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+ process.StartInfo = startInfo;
+ process.Start();
+
+ string? _line;
+ while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
+ {
+ if (_line.Trim() != "")
+ {
+ output.Add(_line);
+ if (_line.Contains("The value provided for the `locale` argument is invalid") ||
+ _line.Contains("No applicable installer found; see Logger.Logs for more details."))
+ {
+ LocaleFound = false;
+ break;
+ }
+ }
+ }
+
+ // Load fallback english locale
+ if (!LocaleFound)
+ {
+ output.Clear();
+ Logger.Info("Winget could not found culture data for package Id=" + details.Package.Id + " and Culture=" +
+ System.Globalization.CultureInfo.CurrentCulture.ToString() + ". Trying to get data for en-US");
+ process = new Process();
+ LocaleFound = true;
+ startInfo = new()
+ {
+ FileName = Manager.WinGetBundledPath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " show " + packageIdentifier +
+ " --disable-interactivity --accept-source-agreements --locale en-US",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+ process.StartInfo = startInfo;
+ process.Start();
+
+ while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
+ {
+ if (_line.Trim() != "")
+ {
+ output.Add(_line);
+ if (_line.Contains("The value provided for the `locale` argument is invalid") ||
+ _line.Contains("No applicable installer found; see Logger.Logs for more details."))
+ {
+ LocaleFound = false;
+ break;
+ }
+ }
+ }
+ }
+
+ // Load default locale
+ if (!LocaleFound)
+ {
+ output.Clear();
+ Logger.Info("Winget could not found culture data for package Id=" + details.Package.Id +
+ " and Culture=en-US. Loading default");
+ LocaleFound = true;
+ process = new Process();
+ startInfo = new()
+ {
+ FileName = Manager.WinGetBundledPath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " show " + packageIdentifier +
+ " --disable-interactivity --accept-source-agreements",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+ process.StartInfo = startInfo;
+ process.Start();
+
+ while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
+ {
+ if (_line.Trim() != "")
+ {
+ output.Add(_line);
+ }
+ }
+ }
+
+ // Parse the output
+ bool IsLoadingDescription = false;
+ bool IsLoadingReleaseNotes = false;
+ bool IsLoadingTags = false;
+ foreach (string __line in output)
+ {
+ try
+ {
+ string line = __line.TrimEnd();
+ if (line == "")
+ {
+ continue;
+ }
+
+ // Check if a multiline field is being loaded
+ if (line.StartsWith(" ") && IsLoadingDescription)
+ {
+ details.Description += "\n" + line.Trim();
+ }
+ else if (line.StartsWith(" ") && IsLoadingReleaseNotes)
+ {
+ details.ReleaseNotes += "\n" + line.Trim();
+ }
+ else if (line.StartsWith(" ") && IsLoadingTags)
+ {
+ details.Tags = details.Tags.Append(line.Trim()).ToArray();
+ }
+
+ // Stop loading multiline fields
+ else if (IsLoadingDescription)
+ {
+ IsLoadingDescription = false;
+ }
+ else if (IsLoadingReleaseNotes)
+ {
+ IsLoadingReleaseNotes = false;
+ }
+ else if (IsLoadingTags)
+ {
+ IsLoadingTags = false;
+ }
+
+ // Check for singleline fields
+ if (line.Contains("Publisher:"))
+ {
+ details.Publisher = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("Author:"))
+ {
+ details.Author = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("Homepage:"))
+ {
+ details.HomepageUrl = new Uri(line.Replace("Homepage:", "").Trim());
+ }
+ else if (line.Contains("License:"))
+ {
+ details.License = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("License Url:"))
+ {
+ details.LicenseUrl = new Uri(line.Replace("License Url:", "").Trim());
+ }
+ else if (line.Contains("Installer SHA256:"))
+ {
+ details.InstallerHash = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("Installer Url:"))
+ {
+ details.InstallerUrl = new Uri(line.Replace("Installer Url:", "").Trim());
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
+ }
+ else if (line.Contains("Release Date:"))
+ {
+ details.UpdateDate = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("Release Notes Url:"))
+ {
+ details.ReleaseNotesUrl = new Uri(line.Replace("Release Notes Url:", "").Trim());
+ }
+ else if (line.Contains("Installer Type:"))
+ {
+ details.InstallerType = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("Description:"))
+ {
+ details.Description = line.Split(":")[1].Trim();
+ IsLoadingDescription = true;
+ }
+ else if (line.Contains("ReleaseNotes"))
+ {
+ details.ReleaseNotes = line.Split(":")[1].Trim();
+ IsLoadingReleaseNotes = true;
+ }
+ else if (line.Contains("Tags"))
+ {
+ details.Tags = new string[0];
+ IsLoadingTags = true;
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn("Error occurred while parsing line value=\"" + _line + "\"");
+ Logger.Warn(e.Message);
+ }
+ }
+
+ return;
+ }
+
+ public async Task GetPackageVersions_Unsafe(WinGet Manager, Package package)
+ {
+ Process p = new()
+ {
+ StartInfo = new ProcessStartInfo()
+ {
+ FileName = Manager.WinGetBundledPath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " show --id " + package.Id +
+ " --exact --versions --accept-source-agreements",
+ UseShellExecute = false,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+
+ ManagerClasses.Classes.ProcessTaskLogger logger =
+ Manager.TaskLogger.CreateNew(LoggableTaskType.LoadPackageVersions, p);
+
+ p.Start();
+
+ string? line;
+ List versions = [];
+ bool DashesPassed = false;
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ logger.AddToStdOut(line);
+ if (!DashesPassed)
+ {
+ if (line.Contains("---"))
+ {
+ DashesPassed = true;
+ }
+ }
+ else
+ {
+ versions.Add(line.Trim());
+ }
+ }
+
+ logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
+ await p.WaitForExitAsync();
+ logger.Close(p.ExitCode);
+ return versions.ToArray();
+ }
+
+ public async Task GetSources_UnSafe(WinGet Manager)
+ {
+ List sources = [];
+
+ Process p = new()
+ {
+ StartInfo = new()
+ {
+ FileName = Manager.Status.ExecutablePath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " source list",
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ }
+ };
+
+ p.Start();
+
+ ManagerClasses.Classes.ProcessTaskLogger
+ logger = Manager.TaskLogger.CreateNew(LoggableTaskType.FindPackages, p);
+
+ bool dashesPassed = false;
+ string? line;
+ while ((line = await p.StandardOutput.ReadLineAsync()) != null)
+ {
+ logger.AddToStdOut(line);
+ try
+ {
+ if (string.IsNullOrEmpty(line))
+ {
+ continue;
+ }
+
+ if (!dashesPassed)
+ {
+ if (line.Contains("---"))
+ {
+ dashesPassed = true;
+ }
+ }
+ else
+ {
+ string[] parts = Regex.Replace(line.Trim(), " {2,}", " ").Split(' ');
+ if (parts.Length > 1)
+ {
+ sources.Add(new ManagerSource(Manager, parts[0].Trim(), new Uri(parts[1].Trim())));
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn(e);
+ }
+ }
+
+ logger.AddToStdErr(await p.StandardError.ReadToEndAsync());
+ await p.WaitForExitAsync();
+ logger.Close(p.ExitCode);
+ return sources.ToArray();
+
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/IWinGetManagerHelpers.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/IWinGetManagerHelpers.cs
new file mode 100644
index 000000000..f70b56521
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/IWinGetManagerHelpers.cs
@@ -0,0 +1,48 @@
+using Microsoft.Management.Deployment;
+using System.Diagnostics;
+using System.Text;
+using System.Text.RegularExpressions;
+using UniGetUI.Core.Data;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.SettingsEngine;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.PackageClasses;
+using WindowsPackageManager.Interop;
+
+namespace UniGetUI.PackageEngine.Managers.WingetManager
+{
+ internal static class WinGetHelper
+ {
+ private static IWinGetManagerHelper? __helper;
+ public static IWinGetManagerHelper Instance
+ {
+ get
+ {
+ if (__helper == null)
+ {
+ __helper = new BundledWinGetHelper();
+ }
+ return __helper;
+ }
+
+ set
+ {
+ __helper = value;
+ }
+ }
+ }
+
+ internal interface IWinGetManagerHelper
+ {
+ public Task GetAvailableUpdates_UnSafe(WinGet Manager);
+ public Task GetInstalledPackages_UnSafe(WinGet Manager);
+ public Task FindPackages_UnSafe(WinGet Manager, string query);
+ public Task GetSources_UnSafe(WinGet Manager);
+ public Task GetPackageVersions_Unsafe(WinGet Manager, Package package);
+ public Task GetPackageDetails_UnSafe(WinGet Manager, PackageDetails details);
+ }
+}
+
+
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/NativeWinGetHelper.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/NativeWinGetHelper.cs
new file mode 100644
index 000000000..c7854c05c
--- /dev/null
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetHelpers/NativeWinGetHelper.cs
@@ -0,0 +1,477 @@
+using System.Diagnostics;
+using System.Diagnostics.Tracing;
+using Microsoft.Management.Deployment;
+using UniGetUI.Core.Logging;
+using UniGetUI.Core.SettingsEngine;
+using UniGetUI.Core.Tools;
+using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers;
+using UniGetUI.PackageEngine.Enums;
+using UniGetUI.PackageEngine.ManagerClasses.Classes;
+using UniGetUI.PackageEngine.PackageClasses;
+using WindowsPackageManager.Interop;
+
+namespace UniGetUI.PackageEngine.Managers.WingetManager;
+
+internal class NativeWinGetHelper : IWinGetManagerHelper
+{
+ public WindowsPackageManagerFactory Factory;
+ public PackageManager WinGetManager;
+
+ public NativeWinGetHelper()
+ {
+ if (Settings.Get("DisableWinGetCOMApi"))
+ throw new Exception("User requested to disable the WinGet COM API, crashing...");
+ if (CoreTools.IsAdministrator())
+ {
+ Logger.Info("Running elevated, WinGet class registration is likely to fail");
+ }
+
+ Factory = new WindowsPackageManagerStandardFactory();
+ WinGetManager = Factory.CreatePackageManager();
+ }
+
+
+ public async Task FindPackages_UnSafe(WinGet Manager, string query)
+ {
+ List Packages = [];
+ ManagerClasses.Classes.NativeTaskLogger logger = Manager.TaskLogger.CreateNew(LoggableTaskType.FindPackages);
+ foreach (string query_part in query.Replace(".", " ").Split(" "))
+ {
+ FindPackagesOptions PackageFilters = Factory.CreateFindPackagesOptions();
+
+ logger.Log("Generating filters...");
+ // Name filter
+ PackageMatchFilter FilterName = Factory.CreatePackageMatchFilter();
+ FilterName.Field = PackageMatchField.Name;
+ FilterName.Value = query_part;
+ FilterName.Option = PackageFieldMatchOption.ContainsCaseInsensitive;
+ PackageFilters.Filters.Add(FilterName);
+
+ // Id filter
+ PackageMatchFilter FilterId = Factory.CreatePackageMatchFilter();
+ FilterId.Field = PackageMatchField.Id;
+ FilterId.Value = query_part;
+ FilterId.Option = PackageFieldMatchOption.ContainsCaseInsensitive;
+ PackageFilters.Filters.Add(FilterId);
+
+ // Load catalogs
+ logger.Log("Loading available catalogs...");
+ IReadOnlyList AvailableCatalogs = WinGetManager.GetPackageCatalogs();
+ Dictionary> FindPackageTasks = [];
+
+ // Spawn Tasks to find packages on catalogs
+ logger.Log("Spawning catalog fetching tasks...");
+ foreach (PackageCatalogReference CatalogReference in AvailableCatalogs.ToArray())
+ {
+ logger.Log($"Begin search on catalog {CatalogReference.Info.Name}");
+ // Connect to catalog
+ CatalogReference.AcceptSourceAgreements = true;
+ ConnectResult result = await CatalogReference.ConnectAsync();
+ if (result.Status == ConnectResultStatus.Ok)
+ {
+ try
+ {
+ // Create task and spawn it
+ Task task = new(() => result.PackageCatalog.FindPackages(PackageFilters));
+ task.Start();
+
+ // Add task to list
+ FindPackageTasks.Add(
+ CatalogReference,
+ task
+ );
+ }
+ catch (Exception e)
+ {
+ logger.Error("WinGet: Catalog " + CatalogReference.Info.Name +
+ " failed to spawn FindPackages task.");
+ logger.Error(e);
+ }
+ }
+ else
+ {
+ logger.Error("WinGet: Catalog " + CatalogReference.Info.Name + " failed to connect.");
+ }
+ }
+
+ // Wait for tasks completion
+ await Task.WhenAll(FindPackageTasks.Values.ToArray());
+ logger.Log($"All catalogs fetched. Fetching results for query piece {query_part}");
+
+ foreach (KeyValuePair> CatalogTaskPair in
+ FindPackageTasks)
+ {
+ try
+ {
+ // Get the source for the catalog
+ ManagerSource source = Manager.GetSourceOrDefault(CatalogTaskPair.Key.Info.Name);
+
+ FindPackagesResult FoundPackages = CatalogTaskPair.Value.Result;
+ foreach (MatchResult package in FoundPackages.Matches.ToArray())
+ {
+ CatalogPackage catPkg = package.CatalogPackage;
+ // Create the Package item and add it to the list
+ logger.Log(
+ $"Found package: {catPkg.Name}|{catPkg.Id}|{catPkg.DefaultInstallVersion.Version} on catalog {source.Name}");
+ Packages.Add(new Package(
+ catPkg.Name,
+ catPkg.Id,
+ catPkg.DefaultInstallVersion.Version,
+ source,
+ Manager
+ ));
+ }
+ }
+ catch (Exception e)
+ {
+ logger.Error("WinGet: Catalog " + CatalogTaskPair.Key.Info.Name +
+ " failed to get available packages.");
+ logger.Error(e);
+ }
+ }
+ }
+
+ logger.Close(0);
+ return Packages.ToArray();
+ }
+
+
+ public async Task GetAvailableUpdates_UnSafe(WinGet Manager)
+ {
+ var logger = Manager.TaskLogger.CreateNew(LoggableTaskType.ListInstalledPackages);
+ List packages = new();
+ foreach (var nativePackage in await Task.Run(() => GetLocalWinGetPackages(logger)))
+ {
+ if (nativePackage.IsUpdateAvailable)
+ {
+ ManagerSource source;
+ source = Manager.GetSourceOrDefault(nativePackage.DefaultInstallVersion.PackageCatalog.Info.Name);
+ packages.Add(new Package(nativePackage.Name, nativePackage.Id, nativePackage.InstalledVersion.Version, nativePackage.DefaultInstallVersion.Version, source, Manager));
+ logger.Log($"Found package {nativePackage.Name} {nativePackage.Id} on source {source.Name}, from version {nativePackage.InstalledVersion.Version} to version {nativePackage.DefaultInstallVersion.Version}");
+ }
+ }
+
+ logger.Close(0);
+ return packages.ToArray();
+
+ }
+
+ public async Task GetInstalledPackages_UnSafe(WinGet Manager)
+ {
+ var logger = Manager.TaskLogger.CreateNew(LoggableTaskType.ListInstalledPackages);
+ List packages = new();
+ foreach (var nativePackage in await Task.Run(() => GetLocalWinGetPackages(logger)))
+ {
+ ManagerSource source;
+ if (nativePackage.DefaultInstallVersion != null)
+ {
+ source = Manager.GetSourceOrDefault(nativePackage.DefaultInstallVersion.PackageCatalog.Info.Name);
+ }
+ else
+ {
+ source = Manager.GetLocalSource(nativePackage.Id);
+ }
+ logger.Log($"Found package {nativePackage.Name} {nativePackage.Id} on source {source.Name}");
+ packages.Add(new Package(nativePackage.Name, nativePackage.Id, nativePackage.InstalledVersion.Version, source, Manager));
+ }
+ logger.Close(0);
+ return packages.ToArray();
+ }
+
+ private IEnumerable GetLocalWinGetPackages(NativeTaskLogger logger)
+ {
+ PackageCatalogReference installedSearchCatalogRef;
+ CreateCompositePackageCatalogOptions createCompositePackageCatalogOptions = Factory.CreateCreateCompositePackageCatalogOptions();
+ foreach(var catalogRef in WinGetManager.GetPackageCatalogs().ToArray())
+ {
+ logger.Log($"Adding catalog {catalogRef.Info.Name} to composite catalog");
+ createCompositePackageCatalogOptions.Catalogs.Add(catalogRef);
+ }
+ createCompositePackageCatalogOptions.CompositeSearchBehavior = CompositeSearchBehavior.LocalCatalogs;
+ installedSearchCatalogRef = WinGetManager.CreateCompositePackageCatalog(createCompositePackageCatalogOptions);
+
+ var ConnectResult = installedSearchCatalogRef.Connect();
+ if (ConnectResult.Status != ConnectResultStatus.Ok)
+ {
+ logger.Error("Failed to connect to installedSearchCatalogRef. Aborting.");
+ logger.Close(1);
+ throw new Exception("WinGet: Failed to connect to composite catalog.");
+ }
+
+ FindPackagesOptions findPackagesOptions = Factory.CreateFindPackagesOptions();
+ PackageMatchFilter filter = Factory.CreatePackageMatchFilter();
+ filter.Field = PackageMatchField.Id;
+ filter.Option = PackageFieldMatchOption.StartsWithCaseInsensitive;
+ filter.Value = "";
+ findPackagesOptions.Filters.Add(filter);
+
+ var TaskResult = ConnectResult.PackageCatalog.FindPackages(findPackagesOptions);
+ List foundPackages = new();
+ foreach(var match in TaskResult.Matches.ToArray())
+ foundPackages.Add(match.CatalogPackage);
+ return foundPackages;
+ }
+
+ public async Task GetSources_UnSafe(WinGet Manager)
+ {
+ List sources = [];
+ ManagerClasses.Classes.NativeTaskLogger logger = Manager.TaskLogger.CreateNew(LoggableTaskType.ListSources);
+
+ foreach (PackageCatalogReference catalog in await Task.Run(() => WinGetManager.GetPackageCatalogs().ToArray()))
+ {
+ try
+ {
+ logger.Log($"Found source {catalog.Info.Name} with argument {catalog.Info.Argument}");
+ sources.Add(new ManagerSource(Manager, catalog.Info.Name, new Uri(catalog.Info.Argument),
+ updateDate: catalog.Info.LastUpdateTime.ToString()));
+ }
+ catch (Exception e)
+ {
+ logger.Error(e);
+ }
+ }
+
+ logger.Close(0);
+ return sources.ToArray();
+ }
+
+ public async Task GetPackageVersions_Unsafe(WinGet Manager, Package package)
+ {
+ NativeTaskLogger logger = Manager.TaskLogger.CreateNew(LoggableTaskType.LoadPackageVersions);
+
+ // Find the native package for the given Package object
+ PackageCatalogReference Catalog = WinGetManager.GetPackageCatalogByName(package.Source.Name);
+ if (Catalog == null)
+ {
+ logger.Error("Failed to get catalog " + package.Source.Name + ". Is the package local?");
+ logger.Close(1);
+ return [];
+ }
+
+ // Connect to catalog
+ Catalog.AcceptSourceAgreements = true;
+ ConnectResult ConnectResult = await Task.Run(() => Catalog.Connect());
+ if (ConnectResult.Status != ConnectResultStatus.Ok)
+ {
+ logger.Error("Failed to connect to catalog " + package.Source.Name);
+ logger.Close(1);
+ return [];
+ }
+
+ // Match only the exact same Id
+ FindPackagesOptions packageMatchFilter = Factory.CreateFindPackagesOptions();
+ PackageMatchFilter filters = Factory.CreatePackageMatchFilter();
+ filters.Field = PackageMatchField.Id;
+ filters.Value = package.Id;
+ filters.Option = PackageFieldMatchOption.Equals;
+ packageMatchFilter.Filters.Add(filters);
+ packageMatchFilter.ResultLimit = 1;
+ Task SearchResult =
+ Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
+
+ if (SearchResult.Result == null || SearchResult.Result.Matches == null ||
+ SearchResult.Result.Matches.Count() == 0)
+ {
+ logger.Error("Failed to find package " + package.Id + " in catalog " + package.Source.Name);
+ logger.Close(1);
+ return [];
+ }
+
+ // Get the Native Package
+ CatalogPackage NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
+ string[] versions = NativePackage.AvailableVersions.Select(x => x.Version).ToArray();
+ foreach (string? version in versions)
+ {
+ logger.Log(version);
+ }
+
+ logger.Close(0);
+ return versions ?? [];
+ }
+
+ public async Task GetPackageDetails_UnSafe(WinGet Manager, PackageDetails details)
+ {
+ ManagerClasses.Classes.NativeTaskLogger logger =
+ Manager.TaskLogger.CreateNew(LoggableTaskType.LoadPackageDetails);
+
+ if (details.Package.Source.Name == "winget")
+ {
+ details.ManifestUrl = new Uri("https://github.com/microsoft/winget-pkgs/tree/master/manifests/"
+ + details.Package.Id[0].ToString().ToLower() + "/"
+ + details.Package.Id.Split('.')[0] + "/"
+ + String.Join("/",
+ details.Package.Id.Contains('.')
+ ? details.Package.Id.Split('.')[1..]
+ : details.Package.Id.Split('.'))
+ );
+ }
+ else if (details.Package.Source.Name == "msstore")
+ {
+ details.ManifestUrl = new Uri("https://apps.microsoft.com/detail/" + details.Package.Id);
+ }
+
+ // Find the native package for the given Package object
+ PackageCatalogReference Catalog = WinGetManager.GetPackageCatalogByName(details.Package.Source.Name);
+ if (Catalog == null)
+ {
+ logger.Error("Failed to get catalog " + details.Package.Source.Name + ". Is the package local?");
+ logger.Close(1);
+ return;
+ }
+
+ // Connect to catalog
+ Catalog.AcceptSourceAgreements = true;
+ ConnectResult ConnectResult = await Task.Run(() => Catalog.Connect());
+ if (ConnectResult.Status != ConnectResultStatus.Ok)
+ {
+ logger.Error("Failed to connect to catalog " + details.Package.Source.Name);
+ logger.Close(1);
+ return;
+ }
+
+ // Match only the exact same Id
+ FindPackagesOptions packageMatchFilter = Factory.CreateFindPackagesOptions();
+ PackageMatchFilter filters = Factory.CreatePackageMatchFilter();
+ filters.Field = PackageMatchField.Id;
+ filters.Value = details.Package.Id;
+ filters.Option = PackageFieldMatchOption.Equals;
+ packageMatchFilter.Filters.Add(filters);
+ packageMatchFilter.ResultLimit = 1;
+ Task SearchResult =
+ Task.Run(() => ConnectResult.PackageCatalog.FindPackages(packageMatchFilter));
+
+ if (SearchResult.Result == null || SearchResult.Result.Matches == null ||
+ SearchResult.Result.Matches.Count() == 0)
+ {
+ logger.Error("WinGet: Failed to find package " + details.Package.Id + " in catalog " +
+ details.Package.Source.Name);
+ logger.Close(1);
+ return;
+ }
+
+ // Get the Native Package
+ CatalogPackage NativePackage = SearchResult.Result.Matches.First().CatalogPackage;
+
+ // Extract data from NativeDetails
+ CatalogPackageMetadata NativeDetails =
+ NativePackage.DefaultInstallVersion.GetCatalogPackageMetadata(Windows.System.UserProfile
+ .GlobalizationPreferences.Languages[0]);
+
+ if (NativeDetails.Author != "")
+ {
+ details.Author = NativeDetails.Author;
+ }
+
+ if (NativeDetails.Description != "")
+ {
+ details.Description = NativeDetails.Description;
+ }
+
+ if (NativeDetails.PackageUrl != "")
+ {
+ details.HomepageUrl = new Uri(NativeDetails.PackageUrl);
+ }
+
+ if (NativeDetails.License != "")
+ {
+ details.License = NativeDetails.License;
+ }
+
+ if (NativeDetails.LicenseUrl != "")
+ {
+ details.LicenseUrl = new Uri(NativeDetails.LicenseUrl);
+ }
+
+ if (NativeDetails.Publisher != "")
+ {
+ details.Publisher = NativeDetails.Publisher;
+ }
+
+ if (NativeDetails.ReleaseNotes != "")
+ {
+ details.ReleaseNotes = NativeDetails.ReleaseNotes;
+ }
+
+ if (NativeDetails.ReleaseNotesUrl != "")
+ {
+ details.ReleaseNotesUrl = new Uri(NativeDetails.ReleaseNotesUrl);
+ }
+
+ if (NativeDetails.Tags != null)
+ {
+ details.Tags = NativeDetails.Tags.ToArray();
+ }
+
+
+ // There is no way yet to retrieve installer URLs right now so this part will be console-parsed.
+ // TODO: Replace this code with native code when available on the COM api
+ Process process = new();
+ List output = [];
+ ProcessStartInfo startInfo = new()
+ {
+ FileName = Manager.WinGetBundledPath,
+ Arguments = Manager.Properties.ExecutableCallArgs + " show --id " + details.Package.Id +
+ " --exact --disable-interactivity --accept-source-agreements --source " +
+ details.Package.Source.Name,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ RedirectStandardInput = true,
+ UseShellExecute = false,
+ CreateNoWindow = true,
+ StandardOutputEncoding = System.Text.Encoding.UTF8
+ };
+ process.StartInfo = startInfo;
+ process.Start();
+
+ logger.Log("Begin loading installers:");
+ logger.Log(" Executable: " + startInfo.FileName);
+ logger.Log(" Arguments: " + startInfo.Arguments);
+
+ // Retrieve the output
+ string? _line;
+ while ((_line = await process.StandardOutput.ReadLineAsync()) != null)
+ {
+ if (_line.Trim() != "")
+ {
+ logger.Log(_line);
+ output.Add(_line);
+ }
+ }
+
+ logger.Error(await process.StandardError.ReadToEndAsync());
+
+ // Parse the output
+ foreach (string __line in output)
+ {
+ try
+ {
+ string line = __line.Trim();
+ if (line.Contains("Installer SHA256:"))
+ {
+ details.InstallerHash = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("Installer Url:"))
+ {
+ details.InstallerUrl = new Uri(line.Replace("Installer Url:", "").Trim());
+ details.InstallerSize = await CoreTools.GetFileSizeAsync(details.InstallerUrl);
+ }
+ else if (line.Contains("Release Date:"))
+ {
+ details.UpdateDate = line.Split(":")[1].Trim();
+ }
+ else if (line.Contains("Installer Type:"))
+ {
+ details.InstallerType = line.Split(":")[1].Trim();
+ }
+ }
+ catch (Exception e)
+ {
+ Logger.Warn("Error occurred while parsing line value=\"" + __line + "\"");
+ Logger.Warn(e.Message);
+ }
+ }
+
+ logger.Close(0);
+ return;
+ }
+}
\ No newline at end of file
diff --git a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetPackageDetailsProvider.cs b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetPackageDetailsProvider.cs
index 96a3f9ef8..8d9419133 100644
--- a/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetPackageDetailsProvider.cs
+++ b/src/UniGetUI.PackageEngine.Managers.WinGet/WinGetPackageDetailsProvider.cs
@@ -202,7 +202,7 @@ protected override async Task GetPackageScreenshots_Unsafe(Package packag
}
Microsoft.Management.Deployment.PackageManager WinGetManager = ((NativeWinGetHelper)WinGetHelper.Instance).WinGetManager;
- WindowsPackageManager.Interop.WindowsPackageManagerStandardFactory Factory = ((NativeWinGetHelper)WinGetHelper.Instance).Factory;
+ WindowsPackageManager.Interop.WindowsPackageManagerFactory Factory = ((NativeWinGetHelper)WinGetHelper.Instance).Factory;
// Find the native package for the given Package object
PackageCatalogReference Catalog = WinGetManager.GetPackageCatalogByName(package.Source.Name);
diff --git a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs
index dd61773d9..5c16b2f5c 100644
--- a/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs
+++ b/src/UniGetUI.PackageEngine.PackageEngine/PEInterface.cs
@@ -11,6 +11,9 @@
namespace UniGetUI.PackageEngine
{
+ ///
+ /// The interface/entry point for the UniGetUI Package Engine
+ ///
public static class PEInterface
{
private const int ManagerLoadTimeout = 10000; // 10 seconds timeout for Package Manager initialization
diff --git a/src/UniGetUI/Interface/Pages/SettingsPage.xaml.cs b/src/UniGetUI/Interface/Pages/SettingsPage.xaml.cs
index 2d4a5ec3e..6c05091c0 100644
--- a/src/UniGetUI/Interface/Pages/SettingsPage.xaml.cs
+++ b/src/UniGetUI/Interface/Pages/SettingsPage.xaml.cs
@@ -122,14 +122,22 @@ public SettingsInterface()
CoreTools.LaunchBatchFile(Path.Join(CoreData.UniGetUIExecutableDirectory, "Assets", "Utilities", "reset_winget_sources.cmd"), CoreTools.Translate("Resetting Winget sources - WingetUI"), RunAsAdmin: true);
};
+ CheckboxCard Winget_DisableCOM = new()
+ {
+ Text = CoreTools.Translate("Use the WinGet COM API to fetch packages"),
+ SettingName = "DisableWinGetCOMApi",
+ };
+ Winget_DisableCOM.StateChanged += (s, e) => PackageManagerExpanders[PEInterface.WinGet].ShowRestartRequiredBanner();
+
CheckboxCard Winget_UseBundled = new()
{
- Text = CoreTools.Translate("Use legacy bundled WinGet instead of PowerShell CMDlets"),
+ Text = CoreTools.Translate("Use bundled WinGet instead of PowerShell CMDlets"),
SettingName = "ForceLegacyBundledWinGet"
};
- ExtraSettingsCards[PEInterface.WinGet].Add(Winget_ResetSources);
+ ExtraSettingsCards[PEInterface.WinGet].Add(Winget_DisableCOM);
ExtraSettingsCards[PEInterface.WinGet].Add(Winget_UseBundled);
+ ExtraSettingsCards[PEInterface.WinGet].Add(Winget_ResetSources);
ButtonCard Scoop_Install = new() { Text = CoreTools.AutoTranslated("Install Scoop"), ButtonText = CoreTools.AutoTranslated("Install") };
Scoop_Install.Click += (s, e) =>
diff --git a/src/UniGetUI/Interface/SoftwarePages/AbstractPackagesPage.xaml.cs b/src/UniGetUI/Interface/SoftwarePages/AbstractPackagesPage.xaml.cs
index 50b519149..9a5a52961 100644
--- a/src/UniGetUI/Interface/SoftwarePages/AbstractPackagesPage.xaml.cs
+++ b/src/UniGetUI/Interface/SoftwarePages/AbstractPackagesPage.xaml.cs
@@ -566,7 +566,7 @@ public void FilterPackages()
FilteredPackages.BlockSorting = true;
foreach (Package match in MatchingList)
{
- if (VisibleManagers.Contains(match.Manager) || VisibleSources.Contains(match.Source))
+ if (VisibleSources.Contains(match.Source) || (!match.Manager.Capabilities.SupportsCustomSources && VisibleManagers.Contains(match.Manager)))
{
FilteredPackages.Add(match);
}
diff --git a/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj b/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj
index 622f013d9..fa7567e3b 100644
--- a/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj
+++ b/src/WindowsPackageManager.Interop/ExternalLibraries.WindowsPackageManager.Interop.csproj
@@ -45,14 +45,14 @@
- Feed the $(TargetDir)\WINMD path to CsWinRT in order to generate the projected classes
NOTE: Suppressing the warning only is not enough as this will cause CoreClrInitFailure (0x80008089) error.
-->
-
+
NU1701
true
none
false
-
+
NU1701
true
none