From cd2ebc1562543af954c06f8397d43d507b67cfff Mon Sep 17 00:00:00 2001
From: Ryan <69221034+ryfu-msft@users.noreply.github.com>
Date: Thu, 31 Oct 2024 12:31:04 -0400
Subject: [PATCH] Fix Repair-WinGetPackageManager cmdlet by retrieving
dependencies from GitHub assets (#4923)
---
.../Commands/CliCommand.cs | 2 +-
.../Commands/UserSettingsCommand.cs | 4 +-
.../Commands/VersionCommand.cs | 4 +-
.../Commands/WinGetPackageManagerCommand.cs | 2 +-
.../Common/WinGetIntegrity.cs | 6 +-
.../Extensions/ReleaseExtensions.cs | 20 +-
.../Helpers/AppxModuleHelper.cs | 195 +++++++++++++++---
.../Helpers/PackageDependency.cs | 23 +++
.../Helpers/WinGetVersion.cs | 28 +--
.../Helpers/WingetCLIWrapper.cs | 8 +-
.../Helpers/WingetDependencies.cs | 20 ++
.../scripts/Initialize-LocalWinGetModules.ps1 | 2 +-
12 files changed, 252 insertions(+), 62 deletions(-)
create mode 100644 src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/PackageDependency.cs
create mode 100644 src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetDependencies.cs
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/CliCommand.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/CliCommand.cs
index b089e14531..1021c3abf8 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/CliCommand.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/CliCommand.cs
@@ -127,7 +127,7 @@ public void ResetAllSources()
private WinGetCLICommandResult Run(string command, string parameters, int timeOut = 60000)
{
var wingetCliWrapper = new WingetCLIWrapper();
- var result = wingetCliWrapper.RunCommand(command, parameters, timeOut);
+ var result = wingetCliWrapper.RunCommand(this, command, parameters, timeOut);
result.VerifyExitCode();
return result;
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/UserSettingsCommand.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/UserSettingsCommand.cs
index 64433e0b6c..cec2838a01 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/UserSettingsCommand.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/UserSettingsCommand.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
//
@@ -42,7 +42,7 @@ public UserSettingsCommand(PSCmdlet psCmdlet)
if (winGetSettingsFilePath == null)
{
var wingetCliWrapper = new WingetCLIWrapper();
- var settingsResult = wingetCliWrapper.RunCommand("settings", "export");
+ var settingsResult = wingetCliWrapper.RunCommand(this, "settings", "export");
// Read the user settings file property.
var userSettingsFile = Utilities.ConvertToHashtable(settingsResult.StdOut)["userSettingsFile"] ?? throw new ArgumentNullException("userSettingsFile");
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/VersionCommand.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/VersionCommand.cs
index 393ee39ee2..1e64235e7d 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/VersionCommand.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/VersionCommand.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
//
@@ -30,7 +30,7 @@ public VersionCommand(PSCmdlet psCmdlet)
///
public void Get()
{
- this.Write(StreamType.Object, WinGetVersion.InstalledWinGetVersion.TagVersion);
+ this.Write(StreamType.Object, WinGetVersion.InstalledWinGetVersion(this).TagVersion);
}
}
}
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs
index 383208c82b..cdf5f16d51 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Commands/WinGetPackageManagerCommand.cs
@@ -169,7 +169,7 @@ private async Task RepairStateMachineAsync(string expectedVersion, bool allUsers
private async Task InstallDifferentVersionAsync(WinGetVersion toInstallVersion, bool allUsers, bool force)
{
- var installedVersion = WinGetVersion.InstalledWinGetVersion;
+ var installedVersion = WinGetVersion.InstalledWinGetVersion(this);
bool isDowngrade = installedVersion.CompareAsDeployment(toInstallVersion) > 0;
string message = $"Installed WinGet version '{installedVersion.TagVersion}' " +
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs
index cd8932e8de..9669da8dbc 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Common/WinGetIntegrity.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
//
@@ -44,7 +44,7 @@ public static void AssertWinGet(PowerShellCmdlet pwshCmdlet, string expectedVers
// Start by calling winget without its WindowsApp PFN path.
// If it succeeds and the exit code is 0 then we are good.
var wingetCliWrapper = new WingetCLIWrapper(false);
- var result = wingetCliWrapper.RunCommand("--version");
+ var result = wingetCliWrapper.RunCommand(pwshCmdlet, "--version");
result.VerifyExitCode();
}
catch (Win32Exception e)
@@ -68,7 +68,7 @@ public static void AssertWinGet(PowerShellCmdlet pwshCmdlet, string expectedVers
{
// This assumes caller knows that the version exist.
WinGetVersion expectedWinGetVersion = new WinGetVersion(expectedVersion);
- var installedVersion = WinGetVersion.InstalledWinGetVersion;
+ var installedVersion = WinGetVersion.InstalledWinGetVersion(pwshCmdlet);
if (expectedWinGetVersion.CompareTo(installedVersion) != 0)
{
throw new WinGetIntegrityException(
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Extensions/ReleaseExtensions.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Extensions/ReleaseExtensions.cs
index 8fc5623a03..15c3c704c9 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Extensions/ReleaseExtensions.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Extensions/ReleaseExtensions.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
//
@@ -24,16 +24,28 @@ internal static class ReleaseExtensions
/// The asset.
public static ReleaseAsset GetAsset(this Release release, string name)
{
- var assets = release.Assets.Where(a => a.Name == name);
+ var asset = TryGetAsset(release, name);
- if (assets.Any())
+ if (asset != null)
{
- return assets.First();
+ return asset;
}
throw new WinGetRepairException(string.Format(Resources.ReleaseAssetNotFound, name));
}
+ ///
+ /// Gets the Asset if present.
+ ///
+ /// GitHub release.
+ /// Name of asset.
+ /// The asset, or null if not found.
+ public static ReleaseAsset? TryGetAsset(this Release release, string name)
+ {
+ var assets = release.Assets.Where(a => a.Name == name);
+ return assets.Any() ? assets.First() : null;
+ }
+
///
/// Gets the asset that ends with the string.
///
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/AppxModuleHelper.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/AppxModuleHelper.cs
index 16fc9d5d9d..409d48ab55 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/AppxModuleHelper.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/AppxModuleHelper.cs
@@ -9,13 +9,17 @@ namespace Microsoft.WinGet.Client.Engine.Helpers
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
+ using System.IO;
+ using System.IO.Compression;
using System.Linq;
using System.Management.Automation;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using Microsoft.WinGet.Client.Engine.Common;
+ using Microsoft.WinGet.Client.Engine.Exceptions;
using Microsoft.WinGet.Client.Engine.Extensions;
using Microsoft.WinGet.Common.Command;
+ using Newtonsoft.Json;
using Octokit;
using Semver;
using static Microsoft.WinGet.Client.Engine.Common.Constants;
@@ -63,8 +67,13 @@ internal class AppxModuleHelper
// Assets
private const string MsixBundleName = "Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle";
+ private const string DependenciesJsonName = "DesktopAppInstaller_Dependencies.json";
+ private const string DependenciesZipName = "DesktopAppInstaller_Dependencies.zip";
private const string License = "License1.xml";
+ // Format of a dependency package such as 'x64\Microsoft.VCLibs.140.00.UWPDesktop_14.0.33728.0_x64.appx'
+ private const string ExtractedDependencyPath = "{0}\\{1}_{2}_{0}.appx";
+
// Dependencies
// VCLibs
private const string VCLibsUWPDesktop = "Microsoft.VCLibs.140.00.UWPDesktop";
@@ -319,53 +328,67 @@ private async Task AddAppInstallerBundleAsync(string releaseTag, bool downgrade,
private async Task InstallDependenciesAsync(string releaseTag)
{
- // A better implementation would use Add-AppxPackage with -DependencyPath, but
- // the Appx module needs to be remoted into Windows PowerShell. When the string[] parameter
- // gets deserialized from Core the result is a single string which breaks Add-AppxPackage.
- // Here we should: if we are in Windows Powershell then run Add-AppxPackage with -DependencyPath
- // if we are in Core, then start powershell.exe and run the same command. Right now, we just
- // do Add-AppxPackage for each one.
- await this.InstallVCLibsDependenciesAsync();
- await this.InstallUiXamlAsync(releaseTag);
+ bool result = await this.InstallDependenciesFromGitHubArchive(releaseTag);
+
+ if (!result)
+ {
+ // A better implementation would use Add-AppxPackage with -DependencyPath, but
+ // the Appx module needs to be remoted into Windows PowerShell. When the string[] parameter
+ // gets deserialized from Core the result is a single string which breaks Add-AppxPackage.
+ // Here we should: if we are in Windows Powershell then run Add-AppxPackage with -DependencyPath
+ // if we are in Core, then start powershell.exe and run the same command. Right now, we just
+ // do Add-AppxPackage for each one.
+ // This method no longer works for versions >1.9 as the vclibs url has been deprecated.
+ await this.InstallVCLibsDependenciesFromUriAsync();
+ await this.InstallUiXamlAsync(releaseTag);
+ }
}
- private async Task InstallVCLibsDependenciesAsync()
+ private Dictionary GetDependenciesByArch(PackageDependency dependencies)
{
- var result = this.ExecuteAppxCmdlet(
- GetAppxPackage,
- new Dictionary
- {
- { Name, VCLibsUWPDesktop },
- });
+ Dictionary appxPackages = new Dictionary();
+ var arch = RuntimeInformation.OSArchitecture;
- // See if the minimum (or greater) version is installed.
- // TODO: Pull the minimum version from the target package
- Version minimumVersion = new Version(VCLibsUWPDesktopVersion);
+ string appxPackageX64 = string.Format(ExtractedDependencyPath, "x64", dependencies.Name, dependencies.Version);
+ string appxPackageX86 = string.Format(ExtractedDependencyPath, "x86", dependencies.Name, dependencies.Version);
+ string appxPackageArm = string.Format(ExtractedDependencyPath, "arm", dependencies.Name, dependencies.Version);
+ string appxPackageArm64 = string.Format(ExtractedDependencyPath, "arm", dependencies.Name, dependencies.Version);
- // Construct the list of frameworks that we want present.
- Dictionary vcLibsDependencies = new Dictionary();
- var arch = RuntimeInformation.OSArchitecture;
if (arch == Architecture.X64)
{
- vcLibsDependencies.Add("x64", VCLibsUWPDesktopX64);
+ appxPackages.Add("x64", appxPackageX64);
}
else if (arch == Architecture.X86)
{
- vcLibsDependencies.Add("x86", VCLibsUWPDesktopX86);
+ appxPackages.Add("x86", appxPackageX86);
}
else if (arch == Architecture.Arm64)
{
// Deployment please figure out for me.
- vcLibsDependencies.Add("x64", VCLibsUWPDesktopX64);
- vcLibsDependencies.Add("x86", VCLibsUWPDesktopX86);
- vcLibsDependencies.Add("arm", VCLibsUWPDesktopArm);
- vcLibsDependencies.Add("arm64", VCLibsUWPDesktopArm64);
+ appxPackages.Add("x64", appxPackageX64);
+ appxPackages.Add("x86", appxPackageX86);
+ appxPackages.Add("arm", appxPackageArm);
+ appxPackages.Add("arm64", appxPackageArm64);
}
else
{
throw new PSNotSupportedException(arch.ToString());
}
+ return appxPackages;
+ }
+
+ private void FindMissingDependencies(Dictionary dependencies, string packageName, string requiredVersion)
+ {
+ var result = this.ExecuteAppxCmdlet(
+ GetAppxPackage,
+ new Dictionary
+ {
+ { Name, packageName },
+ });
+
+ Version minimumVersion = new Version(requiredVersion);
+
if (result != null &&
result.Count > 0)
{
@@ -384,24 +407,30 @@ private async Task InstallVCLibsDependenciesAsync()
string? architectureString = psobject?.Architecture?.ToString();
if (architectureString == null)
{
- this.pwshCmdlet.Write(StreamType.Verbose, $"VCLibs dependency has no architecture value: {psobject?.PackageFullName ?? ""}");
+ this.pwshCmdlet.Write(StreamType.Verbose, $"{packageName} dependency has no architecture value: {psobject?.PackageFullName ?? ""}");
continue;
}
architectureString = architectureString.ToLower();
- if (vcLibsDependencies.ContainsKey(architectureString))
+ if (dependencies.ContainsKey(architectureString))
{
- this.pwshCmdlet.Write(StreamType.Verbose, $"VCLibs {architectureString} dependency satisfied by: {psobject?.PackageFullName ?? ""}");
- vcLibsDependencies.Remove(architectureString);
+ this.pwshCmdlet.Write(StreamType.Verbose, $"{packageName} {architectureString} dependency satisfied by: {psobject?.PackageFullName ?? ""}");
+ dependencies.Remove(architectureString);
}
}
else
{
- this.pwshCmdlet.Write(StreamType.Verbose, $"VCLibs is lower than minimum required version [{minimumVersion}]: {psobject?.PackageFullName ?? ""}");
+ this.pwshCmdlet.Write(StreamType.Verbose, $"{packageName} is lower than minimum required version [{minimumVersion}]: {psobject?.PackageFullName ?? ""}");
}
}
}
+ }
+
+ private async Task InstallVCLibsDependenciesFromUriAsync()
+ {
+ Dictionary vcLibsDependencies = this.GetVCLibsDependencies();
+ this.FindMissingDependencies(vcLibsDependencies, VCLibsUWPDesktop, VCLibsUWPDesktopVersion);
if (vcLibsDependencies.Count != 0)
{
@@ -419,6 +448,108 @@ private async Task InstallVCLibsDependenciesAsync()
}
}
+ // Returns a boolean value indicating whether dependencies were successfully installed from the GitHub release assets.
+ private async Task InstallDependenciesFromGitHubArchive(string releaseTag)
+ {
+ var githubClient = new GitHubClient(RepositoryOwner.Microsoft, RepositoryName.WinGetCli);
+ var release = await githubClient.GetReleaseAsync(releaseTag);
+
+ ReleaseAsset? dependenciesJsonAsset = release.TryGetAsset(DependenciesJsonName);
+ if (dependenciesJsonAsset is null)
+ {
+ return false;
+ }
+
+ using var dependenciesJsonFile = new TempFile();
+ await this.httpClientHelper.DownloadUrlWithProgressAsync(dependenciesJsonAsset.BrowserDownloadUrl, dependenciesJsonFile.FullPath, this.pwshCmdlet);
+
+ using StreamReader r = new StreamReader(dependenciesJsonFile.FullPath);
+ string json = r.ReadToEnd();
+ WingetDependencies? wingetDependencies = JsonConvert.DeserializeObject(json);
+
+ if (wingetDependencies is null)
+ {
+ this.pwshCmdlet.Write(StreamType.Verbose, $"Failed to deserialize dependencies json file.");
+ return false;
+ }
+
+ List missingDependencies = new List();
+ foreach (var dependency in wingetDependencies.Dependencies)
+ {
+ Dictionary dependenciesByArch = this.GetDependenciesByArch(dependency);
+ this.FindMissingDependencies(dependenciesByArch, dependency.Name, dependency.Version);
+
+ foreach (var pair in dependenciesByArch)
+ {
+ missingDependencies.Add(pair.Value);
+ }
+ }
+
+ if (missingDependencies.Count != 0)
+ {
+ using var dependenciesZipFile = new TempFile();
+ using var extractedDirectory = new TempDirectory();
+
+ ReleaseAsset? dependenciesZipAsset = release.TryGetAsset(DependenciesZipName);
+ if (dependenciesZipAsset is null)
+ {
+ this.pwshCmdlet.Write(StreamType.Verbose, $"Dependencies zip asset not found on GitHub asset.");
+ return false;
+ }
+
+ await this.httpClientHelper.DownloadUrlWithProgressAsync(dependenciesZipAsset.BrowserDownloadUrl, dependenciesZipFile.FullPath, this.pwshCmdlet);
+ ZipFile.ExtractToDirectory(dependenciesZipFile.FullPath, extractedDirectory.FullDirectoryPath);
+
+ foreach (var entry in missingDependencies)
+ {
+ string fullPath = System.IO.Path.Combine(extractedDirectory.FullDirectoryPath, entry);
+ if (!File.Exists(fullPath))
+ {
+ this.pwshCmdlet.Write(StreamType.Verbose, $"Package dependency not found in archive: {fullPath}");
+ return false;
+ }
+
+ _ = this.ExecuteAppxCmdlet(
+ AddAppxPackage,
+ new Dictionary
+ {
+ { Path, fullPath },
+ { ErrorAction, Stop },
+ });
+ }
+ }
+
+ return true;
+ }
+
+ private Dictionary GetVCLibsDependencies()
+ {
+ Dictionary vcLibsDependencies = new Dictionary();
+ var arch = RuntimeInformation.OSArchitecture;
+ if (arch == Architecture.X64)
+ {
+ vcLibsDependencies.Add("x64", VCLibsUWPDesktopX64);
+ }
+ else if (arch == Architecture.X86)
+ {
+ vcLibsDependencies.Add("x86", VCLibsUWPDesktopX86);
+ }
+ else if (arch == Architecture.Arm64)
+ {
+ // Deployment please figure out for me.
+ vcLibsDependencies.Add("x64", VCLibsUWPDesktopX64);
+ vcLibsDependencies.Add("x86", VCLibsUWPDesktopX86);
+ vcLibsDependencies.Add("arm", VCLibsUWPDesktopArm);
+ vcLibsDependencies.Add("arm64", VCLibsUWPDesktopArm64);
+ }
+ else
+ {
+ throw new PSNotSupportedException(arch.ToString());
+ }
+
+ return vcLibsDependencies;
+ }
+
private async Task InstallUiXamlAsync(string releaseTag)
{
(string xamlPackageName, string xamlReleaseTag) = GetXamlDependencyVersionInfo(releaseTag);
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/PackageDependency.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/PackageDependency.cs
new file mode 100644
index 0000000000..5920afee1f
--- /dev/null
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/PackageDependency.cs
@@ -0,0 +1,23 @@
+// -----------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
+//
+// -----------------------------------------------------------------------------
+namespace Microsoft.WinGet.Client.Engine.Helpers
+{
+ ///
+ /// A single package dependency.
+ ///
+ internal class PackageDependency
+ {
+ ///
+ /// Gets or sets the name of the dependency.
+ ///
+ public string Name { get; set; } = string.Empty;
+
+ ///
+ /// Gets or sets the version of the dependency.
+ ///
+ public string Version { get; set; } = string.Empty;
+ }
+}
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs
index aea8657ad1..8b53c8fe47 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WinGetVersion.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
//
@@ -7,6 +7,7 @@
namespace Microsoft.WinGet.Client.Engine.Helpers
{
using System;
+ using Microsoft.WinGet.Common.Command;
///
/// WinGetVersion. Parse the string version returned by winget --version to allow comparisons.
@@ -48,19 +49,6 @@ public WinGetVersion(string version)
this.Version = Version.Parse(toParseVersion);
}
- ///
- /// Gets the version of the installed winget.
- ///
- public static WinGetVersion InstalledWinGetVersion
- {
- get
- {
- var wingetCliWrapper = new WingetCLIWrapper();
- var result = wingetCliWrapper.RunCommand("--version");
- return new WinGetVersion(result.StdOut.Replace(Environment.NewLine, string.Empty));
- }
- }
-
///
/// Gets the version as it appears as a tag.
///
@@ -76,6 +64,18 @@ public static WinGetVersion InstalledWinGetVersion
///
public bool IsPrerelease { get; }
+ ///
+ /// Gets the version of the installed winget.
+ ///
+ /// PowerShell cmdlet.
+ /// The WinGetVersion.
+ public static WinGetVersion InstalledWinGetVersion(PowerShellCmdlet pwshCmdlet)
+ {
+ var wingetCliWrapper = new WingetCLIWrapper();
+ var result = wingetCliWrapper.RunCommand(pwshCmdlet, "--version");
+ return new WinGetVersion(result.StdOut.Replace(Environment.NewLine, string.Empty));
+ }
+
///
/// Version.CompareTo taking into account prerelease.
/// From semver: Pre-release versions have a lower precedence than the associated normal version.
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetCLIWrapper.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetCLIWrapper.cs
index 690149622e..a51d43d7da 100644
--- a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetCLIWrapper.cs
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetCLIWrapper.cs
@@ -1,4 +1,4 @@
-// -----------------------------------------------------------------------------
+// -----------------------------------------------------------------------------
//
// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
//
@@ -11,6 +11,7 @@ namespace Microsoft.WinGet.Client.Engine.Helpers
using System.IO;
using Microsoft.WinGet.Client.Engine.Common;
using Microsoft.WinGet.Client.Engine.Exceptions;
+ using Microsoft.WinGet.Common.Command;
///
/// Calls winget directly.
@@ -65,11 +66,12 @@ public static string WinGetFullPath
///
/// Runs winget command with parameters.
///
+ /// PowerShell cmdlet.
/// Command.
/// Parameters.
/// Time out.
/// WinGetCommandResult.
- public WinGetCLICommandResult RunCommand(string command, string? parameters = null, int timeOut = 60000)
+ public WinGetCLICommandResult RunCommand(PowerShellCmdlet pwshCmdlet, string command, string? parameters = null, int timeOut = 60000)
{
string args = command;
if (!string.IsNullOrEmpty(parameters))
@@ -77,6 +79,8 @@ public WinGetCLICommandResult RunCommand(string command, string? parameters = nu
args += ' ' + parameters;
}
+ pwshCmdlet.Write(StreamType.Verbose, $"Running {this.wingetPath} with {args}");
+
Process p = new ()
{
StartInfo = new (this.wingetPath, args)
diff --git a/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetDependencies.cs b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetDependencies.cs
new file mode 100644
index 0000000000..4776a6cf02
--- /dev/null
+++ b/src/PowerShell/Microsoft.WinGet.Client.Engine/Helpers/WingetDependencies.cs
@@ -0,0 +1,20 @@
+// -----------------------------------------------------------------------------
+//
+// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
+//
+// -----------------------------------------------------------------------------
+namespace Microsoft.WinGet.Client.Engine.Helpers
+{
+ using System.Collections.Generic;
+
+ ///
+ /// An object representation of the dependencies json.
+ ///
+ internal class WingetDependencies
+ {
+ ///
+ /// Gets or sets a list of required package dependencies.
+ ///
+ public List Dependencies { get; set; } = new List();
+ }
+}
diff --git a/src/PowerShell/scripts/Initialize-LocalWinGetModules.ps1 b/src/PowerShell/scripts/Initialize-LocalWinGetModules.ps1
index da7c89b1d6..14f859b56a 100644
--- a/src/PowerShell/scripts/Initialize-LocalWinGetModules.ps1
+++ b/src/PowerShell/scripts/Initialize-LocalWinGetModules.ps1
@@ -66,7 +66,7 @@ class WinGetModule
[void]PrepareBinaryFiles([string] $buildRoot, [string] $config)
{
$copyErrors = $null
- Copy-Item "$buildRoot\AnyCpu\$config\PowerShell\$($this.Name)\*" $this.Output -Force -Recurse -ErrorVariable copyErrors -ErrorAction SilentlyContinue
+ Copy-Item "$buildRoot\AnyCpu\$config\PowerShell\$($this.Name)" $this.Output -Force -Recurse -ErrorVariable copyErrors -ErrorAction SilentlyContinue
$copyErrors | ForEach-Object { Write-Warning $_ }
}