winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }