diff --git a/src/UniGetUI.Core.Data/CoreData.cs b/src/UniGetUI.Core.Data/CoreData.cs index 13f46b2cfa..822adfd56c 100644 --- a/src/UniGetUI.Core.Data/CoreData.cs +++ b/src/UniGetUI.Core.Data/CoreData.cs @@ -18,6 +18,29 @@ public static int CODE_PAGE { get => __code_page ??= GetCodePage(); } + + private static Encoding? __console_encoding; + // The encoding CLIs that don't force UTF-8 (e.g. Chocolatey) actually emit their console output in. + public static Encoding ConsoleEncoding + { + get + { + if (__console_encoding is not null) + return __console_encoding; + try + { + Encoding.RegisterProvider(CodePagesEncodingProvider.Instance); + __console_encoding = Encoding.GetEncoding(CODE_PAGE); + } + catch (Exception e) + { + Logger.Warn($"Could not resolve console code page {CODE_PAGE}, falling back to UTF-8"); + Logger.Warn(e); + __console_encoding = Encoding.UTF8; + } + return __console_encoding; + } + } public const string VersionName = "2026.1.0"; // Do not modify this line, use file scripts/set-version.ps1 public const int BuildNumber = 106; // Do not modify this line, use file scripts/set-version.ps1 diff --git a/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj b/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj index b08a63f53b..9277739801 100644 --- a/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj +++ b/src/UniGetUI.Core.Data/UniGetUI.Core.Data.csproj @@ -19,5 +19,6 @@ + diff --git a/src/UniGetUI.PackageEngine.Interfaces/IPackageManager.cs b/src/UniGetUI.PackageEngine.Interfaces/IPackageManager.cs index cfea3855b7..fb5d2f010e 100644 --- a/src/UniGetUI.PackageEngine.Interfaces/IPackageManager.cs +++ b/src/UniGetUI.PackageEngine.Interfaces/IPackageManager.cs @@ -1,3 +1,4 @@ +using System.Text; using UniGetUI.PackageEngine.Classes.Manager.Classes; using UniGetUI.PackageEngine.Classes.Manager.ManagerHelpers; using UniGetUI.PackageEngine.Interfaces.ManagerProviders; @@ -21,6 +22,12 @@ public interface IPackageManager public IPackageOperationHelper OperationHelper { get; } public IReadOnlyList Dependencies { get; } + /// + /// The text encoding this manager's CLI emits its output in. Defaults to UTF-8; managers + /// whose CLI emits in the system console code page (e.g. Chocolatey) must override this. + /// + public Encoding OutputEncoding { get; } + /// /// Initializes the Package Manager (asynchronously). Must be run before using any other method of the manager. /// diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs index 243a6343fa..c15cb35807 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Chocolatey.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.Text; using UniGetUI.Core.Data; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; @@ -18,6 +19,9 @@ namespace UniGetUI.PackageEngine.Managers.ChocolateyManager { public class Chocolatey : BaseNuGet { + // Chocolatey emits its output in the system console code page, not UTF-8. + public override Encoding OutputEncoding => CoreData.ConsoleEncoding; + public static readonly string[] FALSE_PACKAGE_IDS = [ "Directory", @@ -265,7 +269,8 @@ protected override IReadOnlyList GetAvailableUpdates_UnSafe() RedirectStandardInput = true, UseShellExecute = false, CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8, + StandardOutputEncoding = OutputEncoding, + StandardErrorEncoding = OutputEncoding, }, }; @@ -300,7 +305,8 @@ protected override IReadOnlyList _getInstalledPackages_UnSafe() RedirectStandardInput = true, UseShellExecute = false, CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8, + StandardOutputEncoding = OutputEncoding, + StandardErrorEncoding = OutputEncoding, }, }; @@ -368,7 +374,8 @@ protected override void _loadManagerVersion(out string version) RedirectStandardOutput = true, RedirectStandardError = true, CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8, + StandardOutputEncoding = OutputEncoding, + StandardErrorEncoding = OutputEncoding, }, }; process.Start(); diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyDetailsHelper.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyDetailsHelper.cs index afe6e95b13..0a5a010b8d 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyDetailsHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateyDetailsHelper.cs @@ -42,7 +42,8 @@ protected override IReadOnlyList GetInstallableVersions_UnSafe(IPackage RedirectStandardError = true, RedirectStandardInput = true, CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8, + StandardOutputEncoding = Manager.OutputEncoding, + StandardErrorEncoding = Manager.OutputEncoding, }, }; diff --git a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateySourceHelper.cs b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateySourceHelper.cs index b8d951c648..d12ea975e1 100644 --- a/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateySourceHelper.cs +++ b/src/UniGetUI.PackageEngine.Managers.Chocolatey/Helpers/ChocolateySourceHelper.cs @@ -65,7 +65,8 @@ protected override IReadOnlyList GetSources_UnSafe() RedirectStandardInput = true, UseShellExecute = false, CreateNoWindow = true, - StandardOutputEncoding = System.Text.Encoding.UTF8, + StandardOutputEncoding = Manager.OutputEncoding, + StandardErrorEncoding = Manager.OutputEncoding, }, }; diff --git a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs index 56741694d2..bc9ea2524b 100644 --- a/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs +++ b/src/UniGetUI.PackageEngine.Operations/PackageOperations.cs @@ -139,6 +139,8 @@ protected sealed override void PrepareProcessStartInfo() process.StartInfo.FileName = FileName; process.StartInfo.Arguments = Arguments; + process.StartInfo.StandardOutputEncoding = Package.Manager.OutputEncoding; + process.StartInfo.StandardErrorEncoding = Package.Manager.OutputEncoding; ApplyCapabilities( IsAdmin, diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs index 1d6999022c..daa176f0d8 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/Classes/NullPackageManager.cs @@ -1,3 +1,4 @@ +using System.Text; using UniGetUI.Core.IconEngine; using UniGetUI.Core.Tools; using UniGetUI.Interface.Enums; @@ -19,6 +20,7 @@ public class NullPackageManager : IPackageManager public ManagerProperties Properties { get; } public ManagerCapabilities Capabilities { get; } public ManagerStatus Status { get; } + public Encoding OutputEncoding => Encoding.UTF8; public string Id { get => string.IsNullOrWhiteSpace(Properties.Id) ? Properties.Name : Properties.Id; diff --git a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs index c08ef9a594..90bc9c0feb 100644 --- a/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs +++ b/src/UniGetUI.PackageEngine.PackageManagerClasses/Manager/PackageManager.cs @@ -1,3 +1,4 @@ +using System.Text; using UniGetUI.Core.Logging; using UniGetUI.Core.SettingsEngine; using UniGetUI.Core.SettingsEngine.SecureSettings; @@ -41,6 +42,7 @@ public IManagerSource DefaultSource public IMultiSourceHelper SourcesHelper { get; protected set; } = new NullSourceHelper(); public IPackageDetailsHelper DetailsHelper { get; protected set; } = null!; public IPackageOperationHelper OperationHelper { get; protected set; } = null!; + public virtual Encoding OutputEncoding => Encoding.UTF8; private readonly bool _baseConstructorCalled; private bool _ready;