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 $_ } }