ManagementDeploymentFactory.cs (12378B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="ManagementDeploymentFactory.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.WinGet.Client.Engine.Helpers 8 { 9 using System; 10 using System.Collections.Generic; 11 using System.Runtime.InteropServices; 12 using Microsoft.Management.Deployment; 13 using Microsoft.WinGet.Client.Engine.Common; 14 using Microsoft.WinGet.Client.Engine.Exceptions; 15 16 #if NET 17 using WinRT; 18 #endif 19 20 /// <summary> 21 /// Constructs instances of classes from the <see cref="Management.Deployment" /> namespace. 22 /// </summary> 23 internal sealed class ManagementDeploymentFactory 24 { 25 #if USE_PROD_CLSIDS 26 private static readonly Guid PackageManagerClsid = Guid.Parse("C53A4F16-787E-42A4-B304-29EFFB4BF597"); 27 private static readonly Guid FindPackagesOptionsClsid = Guid.Parse("572DED96-9C60-4526-8F92-EE7D91D38C1A"); 28 private static readonly Guid CreateCompositePackageCatalogOptionsClsid = Guid.Parse("526534B8-7E46-47C8-8416-B1685C327D37"); 29 private static readonly Guid InstallOptionsClsid = Guid.Parse("1095F097-EB96-453B-B4E6-1613637F3B14"); 30 private static readonly Guid UninstallOptionsClsid = Guid.Parse("E1D9A11E-9F85-4D87-9C17-2B93143ADB8D"); 31 private static readonly Guid PackageMatchFilterClsid = Guid.Parse("D02C9DAF-99DC-429C-B503-4E504E4AB000"); 32 private static readonly Guid DownloadOptionsClsid = Guid.Parse("4CBABE76-7322-4BE4-9CEA-2589A80682DC"); 33 private static readonly Guid RepairOptionsClsid = Guid.Parse("0498F441-3097-455F-9CAF-148F28293865"); 34 #else 35 private static readonly Guid PackageManagerClsid = Guid.Parse("74CB3139-B7C5-4B9E-9388-E6616DEA288C"); 36 private static readonly Guid FindPackagesOptionsClsid = Guid.Parse("1BD8FF3A-EC50-4F69-AEEE-DF4C9D3BAA96"); 37 private static readonly Guid CreateCompositePackageCatalogOptionsClsid = Guid.Parse("EE160901-B317-4EA7-9CC6-5355C6D7D8A7"); 38 private static readonly Guid InstallOptionsClsid = Guid.Parse("44FE0580-62F7-44D4-9E91-AA9614AB3E86"); 39 private static readonly Guid UninstallOptionsClsid = Guid.Parse("AA2A5C04-1AD9-46C4-B74F-6B334AD7EB8C"); 40 private static readonly Guid PackageMatchFilterClsid = Guid.Parse("3F85B9F4-487A-4C48-9035-2903F8A6D9E8"); 41 private static readonly Guid DownloadOptionsClsid = Guid.Parse("8EF324ED-367C-4880-83E5-BB2ABD0B72F6"); 42 private static readonly Guid RepairOptionsClsid = Guid.Parse("E62BB1E7-C7B2-4AEC-9E28-FB649B30FF03"); 43 #endif 44 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 45 private static readonly Type? PackageManagerType = Type.GetTypeFromCLSID(PackageManagerClsid); 46 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 47 private static readonly Type? FindPackagesOptionsType = Type.GetTypeFromCLSID(FindPackagesOptionsClsid); 48 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 49 private static readonly Type? CreateCompositePackageCatalogOptionsType = Type.GetTypeFromCLSID(CreateCompositePackageCatalogOptionsClsid); 50 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 51 private static readonly Type? InstallOptionsType = Type.GetTypeFromCLSID(InstallOptionsClsid); 52 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 53 private static readonly Type? UninstallOptionsType = Type.GetTypeFromCLSID(UninstallOptionsClsid); 54 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 55 private static readonly Type? PackageMatchFilterType = Type.GetTypeFromCLSID(PackageMatchFilterClsid); 56 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 57 private static readonly Type? DownloadOptionsType = Type.GetTypeFromCLSID(DownloadOptionsClsid); 58 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 59 private static readonly Type? RepairOptionsType = Type.GetTypeFromCLSID(RepairOptionsClsid); 60 61 // These GUIDs correspond to the CSWinRT interface IIDs generated for Microsoft.Management.Deployment.Projection 62 // and are auto-generated by the WinRT tool. 63 private static readonly Guid PackageManagerIid = Guid.Parse("B375E3B9-F2E0-5C93-87A7-B67497F7E593"); 64 private static readonly Guid FindPackagesOptionsIid = Guid.Parse("A5270EDD-7DA7-57A3-BACE-F2593553561F"); 65 private static readonly Guid CreateCompositePackageCatalogOptionsIid = Guid.Parse("21ABAA76-089D-51C5-A745-C85EEFE70116"); 66 private static readonly Guid InstallOptionsIid = Guid.Parse("6EE9DB69-AB48-5E72-A474-33A924CD23B3"); 67 private static readonly Guid UninstallOptionsIid = Guid.Parse("3EBC67F0-8339-594B-8A42-F90B69D02BBE"); 68 private static readonly Guid PackageMatchFilterIid = Guid.Parse("D981ECA3-4DE5-5AD7-967A-698C7D60FC3B"); 69 private static readonly Guid DownloadOptionsIid = Guid.Parse("94C92C4B-43F5-5CA3-BBBE-9F432C9546BC"); 70 private static readonly Guid RepairOptionsIid = Guid.Parse("263F0546-2D7E-53A0-B8D1-75B74817FF18"); 71 72 private static readonly IEnumerable<Architecture> ValidArchs = new Architecture[] { Architecture.X86, Architecture.X64 }; 73 74 private static readonly Lazy<ManagementDeploymentFactory> Lazy = new (() => new ManagementDeploymentFactory()); 75 76 /// <summary> 77 /// Initializes static members of the <see cref="ManagementDeploymentFactory"/> class. 78 /// </summary> 79 static ManagementDeploymentFactory() 80 { 81 if (Utilities.UsesInProcWinget) 82 { 83 PackageManagerSettings settings = new PackageManagerSettings(); 84 settings.SetCallerIdentifier("PowerShellInProc"); 85 } 86 } 87 88 private ManagementDeploymentFactory() 89 { 90 } 91 92 /// <summary> 93 /// Gets the instance object. 94 /// </summary> 95 public static ManagementDeploymentFactory Instance 96 { 97 get { return Lazy.Value; } 98 } 99 100 /// <summary> 101 /// Creates an instance of the <see cref="PackageManager" /> class. 102 /// </summary> 103 /// <returns>A <see cref="PackageManager" /> instance.</returns> 104 public PackageManager CreatePackageManager() 105 { 106 var result = Create<PackageManager>(PackageManagerType, PackageManagerIid); 107 108 if (!Utilities.UsesInProcWinget) 109 { 110 _ = CoAllowSetForegroundWindow(result, IntPtr.Zero); 111 } 112 113 return result; 114 } 115 116 /// <summary> 117 /// Creates an instance of the <see cref="FindPackagesOptions" /> class. 118 /// </summary> 119 /// <returns>A <see cref="FindPackagesOptions" /> instance.</returns> 120 public FindPackagesOptions CreateFindPackagesOptions() 121 { 122 return Create<FindPackagesOptions>(FindPackagesOptionsType, FindPackagesOptionsIid); 123 } 124 125 /// <summary> 126 /// Creates an instance of the <see cref="CreateCompositePackageCatalogOptions" /> class. 127 /// </summary> 128 /// <returns>A <see cref="CreateCompositePackageCatalogOptions" /> instance.</returns> 129 public CreateCompositePackageCatalogOptions CreateCreateCompositePackageCatalogOptions() 130 { 131 return Create<CreateCompositePackageCatalogOptions>(CreateCompositePackageCatalogOptionsType, CreateCompositePackageCatalogOptionsIid); 132 } 133 134 /// <summary> 135 /// Creates an instance of the <see cref="InstallOptions" /> class. 136 /// </summary> 137 /// <returns>An <see cref="InstallOptions" /> instance.</returns> 138 public InstallOptions CreateInstallOptions() 139 { 140 return Create<InstallOptions>(InstallOptionsType, InstallOptionsIid); 141 } 142 143 /// <summary> 144 /// Creates an instance of the <see cref="UninstallOptions" /> class. 145 /// </summary> 146 /// <returns>A <see cref="UninstallOptions" /> instance.</returns> 147 public UninstallOptions CreateUninstallOptions() 148 { 149 return Create<UninstallOptions>(UninstallOptionsType, UninstallOptionsIid); 150 } 151 152 /// <summary> 153 /// Creates an instance of the <see cref="DownloadOptions" /> class. 154 /// </summary> 155 /// <returns>A <see cref="DownloadOptions" /> instance.</returns> 156 public DownloadOptions CreateDownloadOptions() 157 { 158 return Create<DownloadOptions>(DownloadOptionsType, DownloadOptionsIid); 159 } 160 161 /// <summary> 162 /// Creates an instance of the <see cref="PackageMatchFilter" /> class. 163 /// </summary> 164 /// <returns>A <see cref="PackageMatchFilter" /> instance.</returns> 165 public PackageMatchFilter CreatePackageMatchFilter() 166 { 167 return Create<PackageMatchFilter>(PackageMatchFilterType, PackageMatchFilterIid); 168 } 169 170 /// <summary> 171 /// Creates an instance of the <see cref="RepairOptions" /> class. 172 /// </summary> 173 /// <returns>A <see cref="RepairOptions" /> instance.</returns> 174 public RepairOptions CreateRepairOptions() 175 { 176 return Create<RepairOptions>(RepairOptionsType, RepairOptionsIid); 177 } 178 179 [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")] 180 private static T Create<T>(Type? type, in Guid iid) 181 where T : new() 182 { 183 if (type == null) 184 { 185 throw new ArgumentNullException(iid.ToString()); 186 } 187 188 if (Utilities.UsesInProcWinget) 189 { 190 // This doesn't work on Windows PowerShell 191 // If we want to support it, we need something that loads the 192 // Microsoft.Management.Deployment.dll for .NET framework as CsWinRT 193 // does for .NET Core 194 return new T(); 195 } 196 197 object? instance = null; 198 199 if (Utilities.ExecutingAsAdministrator) 200 { 201 int hr = WinRTHelpers.ManualActivation(type.GUID, iid, 0, out instance); 202 203 if (hr < 0) 204 { 205 if (hr == ErrorCode.FileNotFound || hr == ErrorCode.PackageNotRegisteredForUser) 206 { 207 throw new WinGetIntegrityException(IntegrityCategory.AppInstallerNotInstalled); 208 } 209 else 210 { 211 throw new COMException($"Failed to create instance: {hr}", hr); 212 } 213 } 214 } 215 else 216 { 217 instance = Activator.CreateInstance(type); 218 } 219 220 if (instance == null) 221 { 222 throw new ArgumentNullException(); 223 } 224 225 #if NET 226 IntPtr pointer = Marshal.GetIUnknownForObject(instance); 227 return MarshalInterface<T>.FromAbi(pointer); 228 #else 229 return (T)instance; 230 #endif 231 } 232 233 [DllImport("ole32.dll", ExactSpelling = true, PreserveSig = true)] 234 private static extern int CoAllowSetForegroundWindow([MarshalAs(UnmanagedType.IUnknown)] object pUnk, IntPtr reserved); 235 } 236 }