commit 3887bc8188f9dc6ebddecc685a29273edf4962b7 parent fcce38f532439fc4a7294c246c1eb19d146acea4 Author: Ryan Fu <69221034+ryfu-msft@users.noreply.github.com> Date: Mon, 6 Feb 2023 16:32:20 -0800 Use C# wrapper objects for PowerShell cmdlet output (#2871) Diffstat:
15 files changed, 859 insertions(+), 42 deletions(-)
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Commands/FindPackageCommand.cs b/src/PowerShell/Microsoft.WinGet.Client/Commands/FindPackageCommand.cs @@ -5,17 +5,17 @@ // ----------------------------------------------------------------------------- namespace Microsoft.WinGet.Client.Commands -{ +{ using System.Management.Automation; using Microsoft.Management.Deployment; using Microsoft.WinGet.Client.Commands.Common; - using Microsoft.WinGet.Client.Common; - + using Microsoft.WinGet.Client.Common; + /// <summary> /// Searches configured sources for packages. /// </summary> [Cmdlet(VerbsCommon.Find, Constants.WinGetNouns.Package)] - [OutputType(typeof(MatchResult))] + [OutputType(typeof(PSObjects.FoundCatalogPackage))] public sealed class FindPackageCommand : BaseFinderExtendedCommand { /// <summary> @@ -27,7 +27,7 @@ namespace Microsoft.WinGet.Client.Commands var results = this.FindPackages(CompositeSearchBehavior.RemotePackagesFromRemoteCatalogs); for (var i = 0; i < results.Count; i++) { - this.WriteObject(results[i]); + this.WriteObject(new PSObjects.FoundCatalogPackage(results[i].CatalogPackage)); } } } diff --git a/src/PowerShell/Microsoft.WinGet.Client/Commands/GetPackageCommand.cs b/src/PowerShell/Microsoft.WinGet.Client/Commands/GetPackageCommand.cs @@ -15,7 +15,7 @@ namespace Microsoft.WinGet.Client.Commands /// Searches configured sources for packages. /// </summary> [Cmdlet(VerbsCommon.Get, Constants.WinGetNouns.Package)] - [OutputType(typeof(CatalogPackage))] + [OutputType(typeof(PSObjects.InstalledCatalogPackage))] public sealed class GetPackageCommand : BaseFinderExtendedCommand { /// <summary> @@ -27,7 +27,7 @@ namespace Microsoft.WinGet.Client.Commands var results = this.FindPackages(CompositeSearchBehavior.LocalCatalogs); for (var i = 0; i < results.Count; i++) { - this.WriteObject(results[i].CatalogPackage); + this.WriteObject(new PSObjects.InstalledCatalogPackage(results[i].CatalogPackage)); } } } diff --git a/src/PowerShell/Microsoft.WinGet.Client/Commands/GetSourceCommand.cs b/src/PowerShell/Microsoft.WinGet.Client/Commands/GetSourceCommand.cs @@ -7,7 +7,6 @@ namespace Microsoft.WinGet.Client.Commands { using System.Management.Automation; - using Microsoft.Management.Deployment; using Microsoft.WinGet.Client.Commands.Common; using Microsoft.WinGet.Client.Common; @@ -15,7 +14,7 @@ namespace Microsoft.WinGet.Client.Commands /// Retrieves the list of configured sources. /// </summary> [Cmdlet(VerbsCommon.Get, Constants.WinGetNouns.Source)] - [OutputType(typeof(PackageCatalogReference))] + [OutputType(typeof(PSObjects.SourceResult))] public sealed class GetSourceCommand : BaseClientCommand { /// <summary> @@ -36,7 +35,7 @@ namespace Microsoft.WinGet.Client.Commands var results = GetPackageCatalogReferences(this.Name); for (var i = 0; i < results.Count; i++) { - this.WriteObject(results[i]); + this.WriteObject(new PSObjects.SourceResult(results[i])); } } } diff --git a/src/PowerShell/Microsoft.WinGet.Client/Commands/InstallPackageCommand.cs b/src/PowerShell/Microsoft.WinGet.Client/Commands/InstallPackageCommand.cs @@ -21,7 +21,7 @@ namespace Microsoft.WinGet.Client.Commands Constants.WinGetNouns.Package, DefaultParameterSetName = Constants.FoundSet, SupportsShouldProcess = true)] - [OutputType(typeof(InstallResult))] + [OutputType(typeof(PSObjects.InstallResult))] public sealed class InstallPackageCommand : BaseInstallCommand { private ProcessorArchitecture architecture; @@ -66,7 +66,7 @@ namespace Microsoft.WinGet.Client.Commands { InstallOptions options = this.GetInstallOptions(version); InstallResult result = this.InstallPackage(package, options); - this.WriteObject(result); + this.WriteObject(new PSObjects.InstallResult(result)); }); } diff --git a/src/PowerShell/Microsoft.WinGet.Client/Commands/UninstallPackageCommand.cs b/src/PowerShell/Microsoft.WinGet.Client/Commands/UninstallPackageCommand.cs @@ -22,7 +22,7 @@ namespace Microsoft.WinGet.Client.Commands Constants.WinGetNouns.Package, DefaultParameterSetName = Constants.FoundSet, SupportsShouldProcess = true)] - [OutputType(typeof(UninstallResult))] + [OutputType(typeof(PSObjects.UninstallResult))] public sealed class UninstallPackageCommand : BasePackageCommand { /// <summary> @@ -46,7 +46,7 @@ namespace Microsoft.WinGet.Client.Commands { UninstallOptions options = this.GetUninstallOptions(version); UninstallResult result = this.UninstallPackage(package, options); - this.WriteObject(result); + this.WriteObject(new PSObjects.UninstallResult(result)); }); } diff --git a/src/PowerShell/Microsoft.WinGet.Client/Commands/UpdatePackageCommand.cs b/src/PowerShell/Microsoft.WinGet.Client/Commands/UpdatePackageCommand.cs @@ -20,7 +20,7 @@ namespace Microsoft.WinGet.Client.Commands Constants.WinGetNouns.Package, DefaultParameterSetName = Constants.FoundSet, SupportsShouldProcess = true)] - [OutputType(typeof(InstallResult))] + [OutputType(typeof(PSObjects.InstallResult))] public sealed class UpdatePackageCommand : BaseInstallCommand { /// <summary> diff --git a/src/PowerShell/Microsoft.WinGet.Client/Module/Format.ps1xml b/src/PowerShell/Microsoft.WinGet.Client/Module/Format.ps1xml @@ -2,25 +2,63 @@ <Configuration> <ViewDefinitions> <View> - <Name>Microsoft.Management.Deployment.MatchResult</Name> + <Name>Microsoft.WinGet.Client.PSObjects.FoundCatalogPackage</Name> <ViewSelectedBy> - <TypeName>Microsoft.Management.Deployment.MatchResult</TypeName> + <TypeName>Microsoft.WinGet.Client.PSObjects.FoundCatalogPackage</TypeName> </ViewSelectedBy> <TableControl> <TableHeaders> <TableColumnHeader> - <Width>32</Width> <Label>Name</Label> </TableColumnHeader> <TableColumnHeader> - <Width>32</Width> <Label>Id</Label> </TableColumnHeader> <TableColumnHeader> <Label>Version</Label> </TableColumnHeader> <TableColumnHeader> - <Label>Match</Label> + <Label>Source</Label> + </TableColumnHeader> + </TableHeaders> + <TableRowEntries> + <TableRowEntry> + <TableColumnItems> + <TableColumnItem> + <ScriptBlock>$_.Name</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.Id</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.Version</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.Source</ScriptBlock> + </TableColumnItem> + </TableColumnItems> + </TableRowEntry> + </TableRowEntries> + </TableControl> + </View> + <View> + <Name>Microsoft.WinGet.Client.PSObjects.InstalledCatalogPackage</Name> + <ViewSelectedBy> + <TypeName>Microsoft.WinGet.Client.PSObjects.InstalledCatalogPackage</TypeName> + </ViewSelectedBy> + <TableControl> + <TableHeaders> + <TableColumnHeader> + <Label>Name</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>Id</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>Version</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>Available</Label> </TableColumnHeader> <TableColumnHeader> <Label>Source</Label> @@ -30,19 +68,19 @@ <TableRowEntry> <TableColumnItems> <TableColumnItem> - <ScriptBlock>$_.CatalogPackage.Name</ScriptBlock> + <ScriptBlock>$_.Name</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>$_.CatalogPackage.Id</ScriptBlock> + <ScriptBlock>$_.Id</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>$_.CatalogPackage.DefaultInstallVersion.Version</ScriptBlock> + <ScriptBlock>$_.Version</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>'{0}: {1}' -f $_.MatchCriteria.Field,$_.MatchCriteria.Value</ScriptBlock> + <ScriptBlock>if ($_.IsUpdateAvailable) { $_.AvailableVersions[0] }</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>$_.CatalogPackage.DefaultInstallVersion.PackageCatalog.Info.Name</ScriptBlock> + <ScriptBlock>$_.Source</ScriptBlock> </TableColumnItem> </TableColumnItems> </TableRowEntry> @@ -50,14 +88,105 @@ </TableControl> </View> <View> - <Name>Microsoft.Management.Deployment.PackageCatalogReference</Name> + <Name>Microsoft.WinGet.Client.PSObjects.InstallResult</Name> <ViewSelectedBy> - <TypeName>Microsoft.Management.Deployment.PackageCatalogReference</TypeName> + <TypeName>Microsoft.WinGet.Client.PSObjects.InstallResult</TypeName> + </ViewSelectedBy> + <TableControl> + <TableHeaders> + <TableColumnHeader> + <Label>InstallerErrorCode</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>Status</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>RebootRequired</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>ExtendedErrorCode</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>CorrelationData</Label> + </TableColumnHeader> + </TableHeaders> + <TableRowEntries> + <TableRowEntry> + <TableColumnItems> + <TableColumnItem> + <ScriptBlock>$_.InstallerErrorCode</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.Status</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.RebootRequired</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.ExtendedErrorCode</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.CorrelationData</ScriptBlock> + </TableColumnItem> + </TableColumnItems> + </TableRowEntry> + </TableRowEntries> + </TableControl> + </View> + <View> + <Name>Microsoft.WinGet.Client.PSObjects.UninstallResult</Name> + <ViewSelectedBy> + <TypeName>Microsoft.WinGet.Client.PSObjects.UninstallResult</TypeName> + </ViewSelectedBy> + <TableControl> + <TableHeaders> + <TableColumnHeader> + <Label>UninstallerErrorCode</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>Status</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>RebootRequired</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>ExtendedErrorCode</Label> + </TableColumnHeader> + <TableColumnHeader> + <Label>CorrelationData</Label> + </TableColumnHeader> + </TableHeaders> + <TableRowEntries> + <TableRowEntry> + <TableColumnItems> + <TableColumnItem> + <ScriptBlock>$_.UninstallerErrorCode</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.Status</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.RebootRequired</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.ExtendedErrorCode</ScriptBlock> + </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.CorrelationData</ScriptBlock> + </TableColumnItem> + </TableColumnItems> + </TableRowEntry> + </TableRowEntries> + </TableControl> + </View> + <View> + <Name>Microsoft.WinGet.Client.PSObjects.SourceResult</Name> + <ViewSelectedBy> + <TypeName>Microsoft.WinGet.Client.PSObjects.SourceResult</TypeName> </ViewSelectedBy> <TableControl> <TableHeaders> <TableColumnHeader> - <Width>32</Width> <Label>Name</Label> </TableColumnHeader> <TableColumnHeader> @@ -71,13 +200,13 @@ <TableRowEntry> <TableColumnItems> <TableColumnItem> - <ScriptBlock>$_.Info.Name</ScriptBlock> + <ScriptBlock>$_.Name</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>$_.Info.Argument</ScriptBlock> + <ScriptBlock>$_.Argument</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>$_.Info.Type</ScriptBlock> + <ScriptBlock>$_.Type</ScriptBlock> </TableColumnItem> </TableColumnItems> </TableRowEntry> @@ -85,47 +214,52 @@ </TableControl> </View> <View> - <Name>Microsoft.Management.Deployment.CatalogPackage</Name> + <Name>Microsoft.WinGet.Client.PSObjects.PackageVersionInfo</Name> <ViewSelectedBy> - <TypeName>Microsoft.Management.Deployment.CatalogPackage</TypeName> + <TypeName>Microsoft.WinGet.Client.PSObjects.PackageVersionInfo</TypeName> </ViewSelectedBy> <TableControl> <TableHeaders> <TableColumnHeader> - <Width>32</Width> - <Label>Name</Label> + <Label>DisplayName</Label> </TableColumnHeader> <TableColumnHeader> <Label>Id</Label> </TableColumnHeader> <TableColumnHeader> - <Label>Version</Label> + <Label>Publisher</Label> </TableColumnHeader> <TableColumnHeader> - <Label>Available</Label> + <Label>Channel</Label> </TableColumnHeader> <TableColumnHeader> - <Label>Source</Label> + <Label>PackageFamilyNames</Label> </TableColumnHeader> + <TableColumnHeader> + <Label>ProductCodes</Label> + </TableColumnHeader> </TableHeaders> <TableRowEntries> <TableRowEntry> <TableColumnItems> <TableColumnItem> - <ScriptBlock>$_.Name</ScriptBlock> + <ScriptBlock>$_.DisplayName</ScriptBlock> </TableColumnItem> <TableColumnItem> <ScriptBlock>$_.Id</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>$_.InstalledVersion.Version</ScriptBlock> + <ScriptBlock>$_.Publisher</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>if ($_.IsUpdateAvailable) { $_.AvailableVersions[0].Version }</ScriptBlock> + <ScriptBlock>$_.Channel</ScriptBlock> </TableColumnItem> <TableColumnItem> - <ScriptBlock>$_.DefaultInstallVersion.PackageCatalog.Info.Name</ScriptBlock> + <ScriptBlock>$_.PackageFamilyNames</ScriptBlock> </TableColumnItem> + <TableColumnItem> + <ScriptBlock>$_.ProductCodes</ScriptBlock> + </TableColumnItem> </TableColumnItems> </TableRowEntry> </TableRowEntries> diff --git a/src/PowerShell/Microsoft.WinGet.Client/PSObjects/CatalogPackage.cs b/src/PowerShell/Microsoft.WinGet.Client/PSObjects/CatalogPackage.cs @@ -0,0 +1,132 @@ +// ----------------------------------------------------------------------------- +// <copyright file="CatalogPackage.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace Microsoft.WinGet.Client.PSObjects +{ + using System.Linq; + using Microsoft.Management.Deployment; + using Microsoft.WinGet.Client.Exceptions; + + /// <summary> + /// CatalogPackage wrapper object for displaying to PowerShell. + /// </summary> + public abstract class CatalogPackage + { + /// <summary> + /// Initializes a new instance of the <see cref="CatalogPackage"/> class. + /// </summary> + /// <param name="catalogPackage">CatalogPackage COM object.</param> + public CatalogPackage(Management.Deployment.CatalogPackage catalogPackage) + { + this.CatalogPackageCOM = catalogPackage; + } + + /// <summary> + /// Gets the name of the catalog package. + /// </summary> + public string Name + { + get + { + return this.CatalogPackageCOM.Name; + } + } + + /// <summary> + /// Gets the id of the catalog package. + /// </summary> + public string Id + { + get + { + return this.CatalogPackageCOM.Id; + } + } + + /// <summary> + /// Gets a value indicating whether an update is available. + /// </summary> + public bool IsUpdateAvailable + { + get + { + return this.CatalogPackageCOM.IsUpdateAvailable; + } + } + + /// <summary> + /// Gets the source name of the catalog package. + /// </summary> + public string Source + { + get + { + return this.CatalogPackageCOM.DefaultInstallVersion.PackageCatalog.Info.Name; + } + } + + /// <summary> + /// Gets list of strings representing the available versions. + /// </summary> + public string[] AvailableVersions + { + get + { + return this.AvailablePackageVersionIds.Select(i => i.Version).ToArray(); + } + } + + /// <summary> + /// Gets the version of the catalog package. + /// </summary> + public abstract string Version { get; } + + /// <summary> + /// Gets the catalog package COM object. + /// </summary> + protected Management.Deployment.CatalogPackage CatalogPackageCOM { get; } + + /// <summary> + /// Gets a list of available package version ids for the package. + /// </summary> + private PackageVersionId[] AvailablePackageVersionIds + { + get + { + return this.CatalogPackageCOM.AvailableVersions.ToArray(); + } + } + + /// <summary> + /// Checks the installed status of the catalog package. + /// </summary> + /// <returns>CheckInstalledStatus string.</returns> + public string CheckInstalledStatus() + { + return this.CatalogPackageCOM.CheckInstalledStatus().Status.ToString(); + } + + /// <summary> + /// Gets the PackageVersionInfo PSObject that corresponds with the version string. + /// </summary> + /// <param name="version">Version string.</param> + /// <returns>PackageVersionInfo PSObject.</returns> + /// <exception cref="NoPackageFoundException">Throws an exception if no package is found.</exception> + public PackageVersionInfo GetPackageVersionInfo(string version) + { + // get specific version that matches + PackageVersionId packageVersionId = this.AvailablePackageVersionIds.FirstOrDefault(x => x.Version == version); + if (packageVersionId != null) + { + return new PackageVersionInfo(this.CatalogPackageCOM.GetPackageVersionInfo(packageVersionId)); + } + else + { + throw new NoPackageFoundException(); + } + } + } +} diff --git a/src/PowerShell/Microsoft.WinGet.Client/PSObjects/FoundCatalogPackage.cs b/src/PowerShell/Microsoft.WinGet.Client/PSObjects/FoundCatalogPackage.cs @@ -0,0 +1,29 @@ +// ----------------------------------------------------------------------------- +// <copyright file="FoundCatalogPackage.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace Microsoft.WinGet.Client.PSObjects +{ + /// <summary> + /// FoundCatalogPackage wrapper object for displaying to PowerShell. + /// </summary> + public class FoundCatalogPackage : CatalogPackage + { + /// <summary> + /// Initializes a new instance of the <see cref="FoundCatalogPackage"/> class. + /// </summary> + /// <param name="catalogPackage">The catalog package COM object.</param> + public FoundCatalogPackage(Management.Deployment.CatalogPackage catalogPackage) + : base(catalogPackage) + { + } + + /// <inheritdoc/> + public override string Version + { + get { return this.CatalogPackageCOM.DefaultInstallVersion.Version; } + } + } +} diff --git a/src/PowerShell/Microsoft.WinGet.Client/PSObjects/InstallResult.cs b/src/PowerShell/Microsoft.WinGet.Client/PSObjects/InstallResult.cs @@ -0,0 +1,82 @@ +// ----------------------------------------------------------------------------- +// <copyright file="InstallResult.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace Microsoft.WinGet.Client.PSObjects +{ + using System; + + /// <summary> + /// InstallResult wrapper object for displaying to PowerShell. + /// </summary> + public class InstallResult + { + private Management.Deployment.InstallResult installResult; + + /// <summary> + /// Initializes a new instance of the <see cref="InstallResult"/> class. + /// </summary> + /// <param name="installResult">The install result COM object.</param> + public InstallResult(Management.Deployment.InstallResult installResult) + { + this.installResult = installResult; + } + + /// <summary> + /// Gets the correlation data of the install result. + /// </summary> + public string CorrelationData + { + get + { + return this.installResult.CorrelationData; + } + } + + /// <summary> + /// Gets the error code of an install. + /// </summary> + public uint InstallerErrorCode + { + get + { + return this.installResult.InstallerErrorCode; + } + } + + /// <summary> + /// Gets the extended error code exception of the failed install result. + /// </summary> + public Exception ExtendedErrorCode + { + get + { + return this.installResult.ExtendedErrorCode; + } + } + + /// <summary> + /// Gets a value indicating whether a reboot is required. + /// </summary> + public bool RebootRequired + { + get + { + return this.installResult.RebootRequired; + } + } + + /// <summary> + /// Gets the status of the install. + /// </summary> + public string Status + { + get + { + return this.installResult.Status.ToString(); + } + } + } +} diff --git a/src/PowerShell/Microsoft.WinGet.Client/PSObjects/InstalledCatalogPackage.cs b/src/PowerShell/Microsoft.WinGet.Client/PSObjects/InstalledCatalogPackage.cs @@ -0,0 +1,29 @@ +// ----------------------------------------------------------------------------- +// <copyright file="InstalledCatalogPackage.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace Microsoft.WinGet.Client.PSObjects +{ + /// <summary> + /// CatalogPackage wrapper object for displaying to PowerShell. + /// </summary> + public class InstalledCatalogPackage : CatalogPackage + { + /// <summary> + /// Initializes a new instance of the <see cref="InstalledCatalogPackage"/> class. + /// </summary> + /// <param name="catalogPackage">The catalog package COM object.</param> + public InstalledCatalogPackage(Management.Deployment.CatalogPackage catalogPackage) + : base(catalogPackage) + { + } + + /// <inheritdoc/> + public override string Version + { + get { return this.CatalogPackageCOM.InstalledVersion.Version; } + } + } +} diff --git a/src/PowerShell/Microsoft.WinGet.Client/PSObjects/PackageVersionInfo.cs b/src/PowerShell/Microsoft.WinGet.Client/PSObjects/PackageVersionInfo.cs @@ -0,0 +1,103 @@ +// ----------------------------------------------------------------------------- +// <copyright file="PackageVersionInfo.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace Microsoft.WinGet.Client.PSObjects +{ + using System.Linq; + + /// <summary> + /// CatalogPackage wrapper object for displaying to PowerShell. + /// </summary> + public class PackageVersionInfo + { + private Management.Deployment.PackageVersionInfo packageVersionInfo; + + /// <summary> + /// Initializes a new instance of the <see cref="PackageVersionInfo"/> class. + /// </summary> + /// <param name="packageVersionInfo">PackageVersionInfo COM object.</param> + public PackageVersionInfo(Management.Deployment.PackageVersionInfo packageVersionInfo) + { + this.packageVersionInfo = packageVersionInfo; + } + + /// <summary> + /// Gets the name of the package version info. + /// </summary> + public string DisplayName + { + get + { + return this.packageVersionInfo.DisplayName; + } + } + + /// <summary> + /// Gets the id of the package version info. + /// </summary> + public string Id + { + get + { + return this.packageVersionInfo.Id; + } + } + + /// <summary> + /// Gets the publisher of the package version info. + /// </summary> + public string Publisher + { + get + { + return this.packageVersionInfo.Publisher; + } + } + + /// <summary> + /// Gets the channel of the package version info. + /// </summary> + public string Channel + { + get + { + return this.packageVersionInfo.Channel; + } + } + + /// <summary> + /// Gets the list of package family names of the package version info. + /// </summary> + public string[] PackageFamilyNames + { + get + { + return this.packageVersionInfo.PackageFamilyNames.ToArray(); + } + } + + /// <summary> + /// Gets the list of product codes of the package version info. + /// </summary> + public string[] ProductCodes + { + get + { + return this.packageVersionInfo.ProductCodes.ToArray(); + } + } + + /// <summary> + /// Compares the version string with the package version info and returns the CompareResult. + /// </summary> + /// <param name="version">Version string.</param> + /// <returns>CompareResult string.</returns> + public string CompareToVersion(string version) + { + return this.packageVersionInfo.CompareToVersion(version).ToString(); + } + } +} diff --git a/src/PowerShell/Microsoft.WinGet.Client/PSObjects/SourceResult.cs b/src/PowerShell/Microsoft.WinGet.Client/PSObjects/SourceResult.cs @@ -0,0 +1,41 @@ +// ----------------------------------------------------------------------------- +// <copyright file="SourceResult.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace Microsoft.WinGet.Client.PSObjects +{ + /// <summary> + /// SourceResult wrapper object for displaying to PowerShell. + /// </summary> + public class SourceResult + { + /// <summary> + /// Initializes a new instance of the <see cref="SourceResult"/> class. + /// </summary> + /// <param name="catalogReference">The PackageCatalogReference COM object.</param> + public SourceResult(Management.Deployment.PackageCatalogReference catalogReference) + { + var info = catalogReference.Info; + this.Name = info.Name; + this.Argument = info.Argument; + this.Type = info.Type; + } + + /// <summary> + /// Gets the name of the source. + /// </summary> + public string Name { get; private set; } + + /// <summary> + /// Gets the argument of the source. + /// </summary> + public string Argument { get; private set; } + + /// <summary> + /// Gets the type of the source. + /// </summary> + public string Type { get; private set; } + } +} diff --git a/src/PowerShell/Microsoft.WinGet.Client/PSObjects/UninstallResult.cs b/src/PowerShell/Microsoft.WinGet.Client/PSObjects/UninstallResult.cs @@ -0,0 +1,82 @@ +// ----------------------------------------------------------------------------- +// <copyright file="UninstallResult.cs" company="Microsoft Corporation"> +// Copyright (c) Microsoft Corporation. Licensed under the MIT License. +// </copyright> +// ----------------------------------------------------------------------------- + +namespace Microsoft.WinGet.Client.PSObjects +{ + using System; + + /// <summary> + /// UninstallResult wrapper object for displaying to PowerShell. + /// </summary> + public class UninstallResult + { + private Management.Deployment.UninstallResult uninstallResult; + + /// <summary> + /// Initializes a new instance of the <see cref="UninstallResult"/> class. + /// </summary> + /// <param name="uninstallResult">The uninstall result COM object.</param> + public UninstallResult(Management.Deployment.UninstallResult uninstallResult) + { + this.uninstallResult = uninstallResult; + } + + /// <summary> + /// Gets the correlation data of the uninstall result. + /// </summary> + public string CorrelationData + { + get + { + return this.uninstallResult.CorrelationData; + } + } + + /// <summary> + /// Gets the extended error code exception of the failed uninstall result. + /// </summary> + public Exception ExtendedErrorCode + { + get + { + return this.uninstallResult.ExtendedErrorCode; + } + } + + /// <summary> + /// Gets a value indicating whether a reboot is required. + /// </summary> + public bool RebootRequired + { + get + { + return this.uninstallResult.RebootRequired; + } + } + + /// <summary> + /// Gets the status of the uninstall. + /// </summary> + public string Status + { + get + { + return this.uninstallResult.Status.ToString(); + } + } + + /// <summary> + /// Gets the error code of an uninstall. + /// </summary> + public uint UninstallerErrorCode + { + get + { + return this.uninstallResult.UninstallerErrorCode; + } + } + } +} diff --git a/src/PowerShell/tests/Microsoft.WinGet.Client.Tests.ps1 b/src/PowerShell/tests/Microsoft.WinGet.Client.Tests.ps1 @@ -0,0 +1,185 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +<# +.Synopsis + Pester tests related to the Microsoft.WinGet.Client PowerShell module. + The tests require the localhost web server to be running and serving the test data. + 'Invoke-Pester' should be called in an admin powershell window with the 'Microsoft.WinGet.Client' PowerShell module already imported. +#> + +BeforeAll { + # Source Add requires admin privileges, this will only execute successfully in an elevated PowerShell. + wingetdev source add 'TestSource' 'https://localhost:5001/TestKit/' +} + +Describe 'Get-WinGetSource' { + + It 'Get Test Source' { + $source = Get-WinGetSource -Name 'TestSource' + $source.Name | Should -Be 'TestSource' + $source.Argument | Should -Be 'https://localhost:5001/TestKit/' + $source.Type | Should -Be 'Microsoft.PreIndexed.Package' + } +} + +Describe 'Find-WinGetPackage' { + It 'Given no parameters, lists all available packages' { + $allPackages = Find-WinGetPackage -Source TestSource + $allPackages.Count | Should -BeGreaterThan 0 + } + + It 'Find by Id' { + $package = Find-WinGetPackage -Source 'TestSource' -Id 'AppInstallerTest.TestExeInstaller' + + $package | Should -Not -BeNullOrEmpty -ErrorAction Stop + $package.Name | Should -Be 'TestExeInstaller' + $package.Id | Should -Be 'AppInstallerTest.TestExeInstaller' + $package.Version | Should -Be '2.0.0.0' + $package.Source | Should -Be 'TestSource' + } + + It 'Find by Name' { + $package = Find-WinGetPackage -Source 'TestSource' -Name 'TestPortableExe' + + $package | Should -Not -BeNullOrEmpty -ErrorAction Stop + $package[0].Name | Should -Be 'TestPortableExe' + $package[1].Name | Should -Be 'TestPortableExeWithCommand' + } + + It 'Find by Name sort by Version' { + $package = Find-WinGetPackage -Source 'TestSource' -Name 'TestPortableExe' | Sort-Object 'Version' + + $package | Should -Not -BeNullOrEmpty -ErrorAction Stop + $package[0].Name | Should -Be 'TestPortableExeWithCommand' + $package[1].Name | Should -Be 'TestPortableExe' + } + + It 'Find package and verify PackageVersionInfo' { + $package = Find-WinGetPackage -Source 'TestSource' -Id 'AppInstallerTest.TestPortableExe' -Exact + + $package | Should -Not -BeNullOrEmpty -ErrorAction Stop + $package.AvailableVersions[0] | Should -Be '3.0.0.0' + $package.AvailableVersions[1] | Should -Be '2.0.0.0' + $package.AvailableVersions.Count | Should -Be 4 + + $packageVersionInfo = $package.GetPackageVersionInfo("3.0.0.0") + $packageVersionInfo.DisplayName | Should -Be 'TestPortableExe' + $packageVersionInfo.Id | Should -Be 'AppInstallerTest.TestPortableExe' + $packageVersionInfo.CompareToVersion("2.0.0.0") | Should -Be 'Greater' + $packageVersionInfo.CompareToVersion("4.0.0.0") | Should -Be 'Lesser' + } +} + +Describe 'Install|Update|Uninstall-WinGetPackage' { + + It 'Install by Id' { + $result = Install-WinGetPackage -Id AppInstallerTest.TestExeInstaller -Version '1.0.0.0' + + $result.InstallerErrorCode | Should -Be 0 + $result.Status | Should -Be 'Ok' + $result.RebootRequired | Should -Be 'False' + } + + It 'Install by exact Name and Version' { + $result = Install-WinGetPackage -Name TestPortableExe -Version '2.0.0.0' -Exact + + $result.InstallerErrorCode | Should -Be 0 + $result.Status | Should -Be 'Ok' + $result.RebootRequired | Should -Be 'False' + } + + It 'Update by Id' { + $result = Update-WinGetPackage -Id AppInstallerTest.TestExeInstaller + + $result.InstallerErrorCode | Should -Be 0 + $result.Status | Should -Be 'Ok' + $result.RebootRequired | Should -Be 'False' + } + + It 'Update by Name and Version' { + $result = Update-WinGetPackage -Name TestPortableExe + + $result.InstallerErrorCode | Should -Be 0 + $result.Status | Should -Be 'Ok' + $result.RebootRequired | Should -Be 'False' + } + + It 'Uninstall by Id' { + $result = Uninstall-WinGetPackage -Id AppInstallerTest.TestExeInstaller + + $result.UninstallerErrorCode | Should -Be 0 + $result.Status | Should -Be 'Ok' + $result.RebootRequired | Should -Be 'False' + } + + It 'Uninstall by Name' { + $result = Uninstall-WinGetPackage -Name TestPortableExe + + $result.UninstallerErrorCode | Should -Be 0 + $result.Status | Should -Be 'Ok' + $result.RebootRequired | Should -Be 'False' + } + + AfterAll { + # Uninstall all test packages after each for proper cleanup. + $testExe = Get-WinGetPackage -Id AppInstallerTest.TestExeInstaller + if ($testExe.Count -gt 0) + { + Uninstall-WinGetPackage -Id AppInstallerTest.TestExeInstaller + } + + $testPortable = Get-WinGetPackage -Id AppInstallerTest.TestPortableExe + if ($testPortable.Count -gt 0) + { + Uninstall-WinGetPackage -Id AppInstallerTest.TestPortableExe + } + } +} + +Describe 'Get-WinGetPackage' { + + It 'Install by Id' { + $result = Install-WinGetPackage -Id AppInstallerTest.TestExeInstaller -Version '1.0.0.0' + + $result.InstallerErrorCode | Should -Be 0 + $result.Status | Should -Be 'Ok' + $result.RebootRequired | Should -Be 'False' + } + + It 'Get package by Id' { + $result = Get-WinGetPackage -Id AppInstallerTest.TestExeInstaller + + $result | Should -Not -BeNullOrEmpty -ErrorAction Stop + $result.Name | Should -Be 'TestExeInstaller' + $result.Id | Should -Be 'AppInstallerTest.TestExeInstaller' + $result.Version | Should -Be '1.0.0.0' + $result.Source | Should -Be 'TestSource' + $result.AvailableVersions[0] | Should -Be '2.0.0.0' + } + + It 'Get package by Name' { + $result = Get-WinGetPackage -Name TestExeInstaller + + $result | Should -Not -BeNullOrEmpty -ErrorAction Stop + $result.Name | Should -Be 'TestExeInstaller' + $result.Id | Should -Be 'AppInstallerTest.TestExeInstaller' + $result.Version | Should -Be '1.0.0.0' + $result.Source | Should -Be 'TestSource' + $result.AvailableVersions[0] | Should -Be '2.0.0.0' + } + + AfterAll { + # Uninstall all test packages after each for proper cleanup. + $testExe = Get-WinGetPackage -Id AppInstallerTest.TestExeInstaller + if ($testExe.Count -gt 0) + { + Uninstall-WinGetPackage -Id AppInstallerTest.TestExeInstaller + } + } +} + +AfterAll { + # Source Remove requires admin privileges, this will only execute successfully in an elevated PowerShell. + wingetdev source remove 'TestSource' +}+ \ No newline at end of file