RepairPackageCommand.cs (6273B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="RepairPackageCommand.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.WinGet.Client.Engine.Commands 8 { 9 using System; 10 using System.Management.Automation; 11 using System.Threading.Tasks; 12 using Microsoft.Management.Deployment; 13 using Microsoft.WinGet.Client.Engine.Commands.Common; 14 using Microsoft.WinGet.Client.Engine.Exceptions; 15 using Microsoft.WinGet.Client.Engine.Helpers; 16 using Microsoft.WinGet.Client.Engine.PSObjects; 17 using Microsoft.WinGet.Resources; 18 19 /// <summary> 20 /// This class defines the repair package command. 21 /// </summary> 22 public sealed class RepairPackageCommand : PackageCommand 23 { 24 /// <summary> 25 /// Initializes a new instance of the <see cref="RepairPackageCommand"/> class. 26 /// </summary> 27 /// <param name="psCmdlet">Caller cmdlet.</param> 28 /// <param name="psCatalogPackage">PSCatalogPackage.</param> 29 /// <param name="allowHashMismatch">To skip the installer hash validation check.</param> 30 /// <param name="force">To continue upon non security related failures.</param> 31 /// <param name="version">Version to repair.</param> 32 /// <param name="log">Logging file location.</param> 33 /// <param name="id">Package identifier.</param> 34 /// <param name="name">Name of package.</param> 35 /// <param name="moniker">Moniker of package.</param> 36 /// <param name="source">Source to search. if null, all are searched.</param> 37 /// <param name="query">Match against any field of a package.</param> 38 public RepairPackageCommand( 39 PSCmdlet psCmdlet, 40 bool allowHashMismatch, 41 bool force, 42 PSCatalogPackage psCatalogPackage, 43 string version, 44 string log, 45 string id, 46 string name, 47 string moniker, 48 string source, 49 string[] query) 50 : base(psCmdlet) 51 { 52 this.Force = force; 53 this.AllowHashMismatch = allowHashMismatch; 54 55 if (psCatalogPackage != null) 56 { 57 this.CatalogPackage = psCatalogPackage; 58 } 59 60 this.Version = version; 61 62 this.Id = id; 63 this.Name = name; 64 this.Moniker = moniker; 65 this.Source = source; 66 this.Query = query; 67 68 this.Log = log; 69 } 70 71 /// <summary> 72 /// Gets or sets the path to the logging file. 73 /// </summary> 74 private string? Log { get; set; } 75 76 /// <summary> 77 /// Gets or sets a value indicating whether to continue upon non security related failures. 78 /// </summary> 79 private bool Force { get; set; } 80 81 /// <summary> 82 /// Gets or sets a value indicating whether to skip the installer hash validation check. 83 /// </summary> 84 private bool AllowHashMismatch { get; set; } 85 86 /// <summary> 87 /// Process repair package. 88 /// </summary> 89 /// <param name="psPackageFieldMatchOption">PSPackageFieldMatchOption.</param> 90 /// <param name="psPackageRepairMode">PSPackageRepairMode.</param> 91 public void Repair( 92 string psPackageFieldMatchOption, 93 string psPackageRepairMode) 94 { 95 var result = this.Execute( 96 async () => await this.GetPackageAndExecuteAsync( 97 CompositeSearchBehavior.AllCatalogs, 98 PSEnumHelpers.ToPackageFieldMatchOption(psPackageFieldMatchOption), 99 async (package, version) => 100 { 101 var repairOptions = this.GetRepairOptions(version, PSEnumHelpers.ToPackageRepairMode(psPackageRepairMode)); 102 return await this.RepairPackageAsync(package, repairOptions); 103 })); 104 105 if (result != null) 106 { 107 if (result.Item1.Status == RepairResultStatus.RepairError 108 && result.Item1.ExtendedErrorCode != null) 109 { 110 if (result.Item1.ExtendedErrorCode.InnerException != null) 111 { 112 throw new WinGetRepairPackageException(result.Item1.ExtendedErrorCode.HResult, result.Item1.RepairerErrorCode, result.Item1.ExtendedErrorCode.InnerException); 113 } 114 115 throw new WinGetRepairPackageException(result.Item1.ExtendedErrorCode.HResult, result.Item1.RepairerErrorCode); 116 } 117 118 this.Write(WinGet.Common.Command.StreamType.Object, new PSRepairResult(result.Item1, result.Item2)); 119 } 120 } 121 122 private RepairOptions GetRepairOptions( 123 PackageVersionId? version, 124 PackageRepairMode repairMode) 125 { 126 var options = ManagementDeploymentFactory.Instance.CreateRepairOptions(); 127 options.AllowHashMismatch = this.AllowHashMismatch; 128 options.Force = this.Force; 129 130 if (this.Log != null) 131 { 132 options.LogOutputPath = this.Log; 133 } 134 135 options.PackageRepairMode = repairMode; 136 137 if (version != null) 138 { 139 options.PackageVersionId = version; 140 } 141 142 return options; 143 } 144 145 private async Task<RepairResult> RepairPackageAsync( 146 CatalogPackage catalogPackage, 147 RepairOptions repairOptions) 148 { 149 var progressOperation = new RepairOperationWithProgress( 150 this, 151 string.Format(Resources.ProgressRecordActivityRepairing, catalogPackage.Name)); 152 153 return await progressOperation.ExecuteAsync( 154 () => PackageManagerWrapper.Instance.RepairPackageAsync(catalogPackage, repairOptions)); 155 } 156 } 157 }