mirror of
https://github.com/marticliment/WinGet-API-from-CSharp
synced 2026-06-21 13:57:37 +00:00
Add code
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WindowsPackageManager Interop\WindowsPackageManager Interop.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,61 @@
|
||||
using System.Security.Principal;
|
||||
|
||||
// Include WinGet Namespace
|
||||
using WindowsPackageManager.Interop;
|
||||
|
||||
namespace WingetTest
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static public void Main(string[] args)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
Console.WriteLine(" ");
|
||||
Console.Write("Enter search query: ");
|
||||
string? Query = Console.ReadLine();
|
||||
if(Query == null || Query == "")
|
||||
break;
|
||||
|
||||
FindPackagesForQuery(Query).Wait();
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task FindPackagesForQuery(string Query)
|
||||
{
|
||||
WindowsPackageManagerFactory WinGetFactory;
|
||||
bool IsAdministrator = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
|
||||
|
||||
// If the user is an administrator, use the elevated factory. Otherwhise COM will crash
|
||||
if(IsAdministrator)
|
||||
WinGetFactory = new WindowsPackageManagerElevatedFactory();
|
||||
else
|
||||
WinGetFactory = new WindowsPackageManagerStandardFactory();
|
||||
|
||||
// Create Package Manager and get available catalogs
|
||||
var Manager = WinGetFactory.CreatePackageManager();
|
||||
var AvailableCatalogs = Manager.GetPackageCatalogs();
|
||||
|
||||
foreach (var Catalog in AvailableCatalogs.ToArray())
|
||||
{
|
||||
// Create a filter to search for packages
|
||||
var FilterList = WinGetFactory.CreateFindPackagesOptions();
|
||||
|
||||
// Add the query to the filter
|
||||
var NameFilter = WinGetFactory.CreatePackageMatchFilter();
|
||||
NameFilter.Field = Microsoft.Management.Deployment.PackageMatchField.Name;
|
||||
NameFilter.Value = Query;
|
||||
FilterList.Filters.Add(NameFilter);
|
||||
|
||||
// Find the packages with the filters
|
||||
var SearchResults = await Catalog.Connect().PackageCatalog.FindPackagesAsync(FilterList);
|
||||
foreach (var Match in SearchResults.Matches.ToArray())
|
||||
{
|
||||
// Print the packages
|
||||
var Package = Match.CatalogPackage;
|
||||
Console.WriteLine(Package.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 17
|
||||
VisualStudioVersion = 17.10.34707.107
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WindowsPackageManager Interop", "WindowsPackageManager Interop\WindowsPackageManager Interop.csproj", "{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo Console App", "Demo Console App\Demo Console App.csproj", "{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|arm64 = Debug|arm64
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|arm64 = Release|arm64
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|Any CPU.ActiveCfg = Debug|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|Any CPU.Build.0 = Debug|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|arm64.ActiveCfg = Debug|arm64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|arm64.Build.0 = Debug|arm64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|x64.Build.0 = Debug|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Debug|x86.Build.0 = Debug|x86
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|Any CPU.ActiveCfg = Release|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|Any CPU.Build.0 = Release|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|arm64.ActiveCfg = Release|arm64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|arm64.Build.0 = Release|arm64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|x64.ActiveCfg = Release|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|x64.Build.0 = Release|x64
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|x86.ActiveCfg = Release|x86
|
||||
{39D02ACA-38AC-41B4-8ED4-DC591AAC5B1F}.Release|x86.Build.0 = Release|x86
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|arm64.ActiveCfg = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|arm64.Build.0 = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|arm64.ActiveCfg = Release|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|arm64.Build.0 = Release|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|x64.Build.0 = Release|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{D30DB5C6-8D6E-4EA9-99C5-C3B495C0109C}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {E855C1C8-5A5C-45A1-BBD0-5253A0E190F2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
|
||||
namespace WindowsPackageManager.Interop;
|
||||
|
||||
public class WinGetConfigurationException : Exception
|
||||
{
|
||||
// WinGet Configuration error codes:
|
||||
// https://github.com/microsoft/winget-cli/blob/master/src/PowerShell/Microsoft.WinGet.Configuration.Engine/Exceptions/ErrorCodes.cs
|
||||
public const int WingetConfigErrorInvalidConfigurationFile = unchecked((int)0x8A15C001);
|
||||
public const int WingetConfigErrorInvalidYaml = unchecked((int)0x8A15C002);
|
||||
public const int WingetConfigErrorInvalidFieldType = unchecked((int)0x8A15C003);
|
||||
public const int WingetConfigErrorUnknownConfigurationFileVersion = unchecked((int)0x8A15C004);
|
||||
public const int WingetConfigErrorSetApplyFailed = unchecked((int)0x8A15C005);
|
||||
public const int WingetConfigErrorDuplicateIdentifier = unchecked((int)0x8A15C006);
|
||||
public const int WingetConfigErrorMissingDependency = unchecked((int)0x8A15C007);
|
||||
public const int WingetConfigErrorDependencyUnsatisfied = unchecked((int)0x8A15C008);
|
||||
public const int WingetConfigErrorAssertionFailed = unchecked((int)0x8A15C009);
|
||||
public const int WingetConfigErrorManuallySkipped = unchecked((int)0x8A15C00A);
|
||||
public const int WingetConfigErrorWarningNotAccepted = unchecked((int)0x8A15C00B);
|
||||
public const int WingetConfigErrorSetDependencyCycle = unchecked((int)0x8A15C00C);
|
||||
public const int WingetConfigErrorInvalidFieldValue = unchecked((int)0x8A15C00D);
|
||||
public const int WingetConfigErrorMissingField = unchecked((int)0x8A15C00E);
|
||||
|
||||
// WinGet Configuration unit error codes:
|
||||
public const int WinGetConfigUnitNotFound = unchecked((int)0x8A15C101);
|
||||
public const int WinGetConfigUnitNotFoundRepository = unchecked((int)0x8A15C102);
|
||||
public const int WinGetConfigUnitMultipleMatches = unchecked((int)0x8A15C103);
|
||||
public const int WinGetConfigUnitInvokeGet = unchecked((int)0x8A15C104);
|
||||
public const int WinGetConfigUnitInvokeTest = unchecked((int)0x8A15C105);
|
||||
public const int WinGetConfigUnitInvokeSet = unchecked((int)0x8A15C106);
|
||||
public const int WinGetConfigUnitModuleConflict = unchecked((int)0x8A15C107);
|
||||
public const int WinGetConfigUnitImportModule = unchecked((int)0x8A15C108);
|
||||
public const int WinGetConfigUnitInvokeInvalidResult = unchecked((int)0x8A15C109);
|
||||
public const int WinGetConfigUnitSettingConfigRoot = unchecked((int)0x8A15C110);
|
||||
public const int WinGetConfigUnitImportModuleAdmin = unchecked((int)0x8A15C111);
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
CoCreateInstance
|
||||
CoMarshalInterface
|
||||
CoUnmarshalInterface
|
||||
CreateStreamOnHGlobal
|
||||
HRESULT_FROM_WIN32
|
||||
MSHCTX
|
||||
MSHLFLAGS
|
||||
@@ -0,0 +1,67 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0-windows10.0.19041.0</TargetFramework>
|
||||
<TargetPlatformMinVersion>10.0.19041.0</TargetPlatformMinVersion>
|
||||
<SupportedOSPlatformVersion>10.0.19041.0</SupportedOSPlatformVersion>
|
||||
<RootNamespace>DevHome.SetupFlow.Common</RootNamespace>
|
||||
<Platforms>x86;x64;arm64</Platforms>
|
||||
<RuntimeIdentifiers>win-x86;win-x64;win-arm64</RuntimeIdentifiers>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<!--
|
||||
CsWinRT properties:
|
||||
https://github.com/microsoft/CsWinRT/blob/master/nuget/readme.md
|
||||
-->
|
||||
<PropertyGroup>
|
||||
<CsWinRTWindowsMetadata>10.0.19041.0</CsWinRTWindowsMetadata>
|
||||
<CsWinRTIncludes>Microsoft.Management.Deployment</CsWinRTIncludes>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<CsWinRTInputs Include="$(TargetDir)\Microsoft.Management.Deployment.winmd" />
|
||||
<Content Include="$(TargetDir)\Microsoft.Management.Deployment.winmd" Link="Microsoft.Management.Deployment.winmd" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="$(TargetDir)\Microsoft.Management.Configuration.dll" Link="Microsoft.Management.Configuration.dll" CopyToOutputDirectory="PreserveNewest" />
|
||||
<Content Include="$(TargetDir)\Microsoft.Management.Configuration.winmd" Link="Microsoft.Management.Configuration.winmd" CopyToOutputDirectory="PreserveNewest" />
|
||||
|
||||
<!-- This DLL from the winget COM interop package allows activating the winget server elevated -->
|
||||
<Content Include="$(TargetDir)\winrtact.dll" Link="winrtact.dll" CopyToOutputDirectory="PreserveNewest" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Management.Infrastructure" Version="3.0.0" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWinRT" Version="2.0.7" />
|
||||
<PackageReference Include="Microsoft.Windows.CsWin32" Version="0.3.49-beta">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
<!--
|
||||
Microsoft.WindowsPackageManager.ComInterop nuget targets .NET Framework:
|
||||
https://www.nuget.org/packages/Microsoft.WindowsPackageManager.ComInterop#readme-body-tab
|
||||
To workaround this issue in this .net project:
|
||||
- Suppress warning 1701 (Package not compatible)
|
||||
- Do not include nuget assets
|
||||
- Generate a property for this package so the path can be referenced
|
||||
- Copy the WINMD to the $(TargetDir) before the build starts
|
||||
- Feed the $(TargetDir)\WINMD path to CsWinRT in order to generate the projected classes
|
||||
NOTE: Suppressing the warning only is not enough as this will cause CoreClrInitFailure (0x80008089) error.
|
||||
-->
|
||||
<PackageReference Include="Microsoft.WindowsPackageManager.ComInterop" Version="1.7.10091-preview">
|
||||
<NoWarn>NU1701</NoWarn>
|
||||
<GeneratePathProperty>true</GeneratePathProperty>
|
||||
<IncludeAssets>none</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.WindowsPackageManager.Configuration.OutOfProc" Version="1.7.10091-preview">
|
||||
<GeneratePathProperty>True</GeneratePathProperty>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CopyWinmdToTargetDir" BeforeTargets="BeforeBuild">
|
||||
<Copy SourceFiles="$(PkgMicrosoft_WindowsPackageManager_ComInterop)\lib\Microsoft.Management.Deployment.winmd" DestinationFolder="$(TargetDir)" />
|
||||
<Copy SourceFiles="$(PkgMicrosoft_WindowsPackageManager_ComInterop)\runtimes\win10-$(Platform)\native\winrtact.dll" DestinationFolder="$(TargetDir)" />
|
||||
<Copy SourceFiles="$(PkgMicrosoft_WindowsPackageManager_Configuration_OutOfProc)\runtimes\win10-$(Platform)\native\Microsoft.Management.Configuration.dll" DestinationFolder="$(TargetDir)" />
|
||||
<Copy SourceFiles="$(PkgMicrosoft_WindowsPackageManager_Configuration_OutOfProc)\runtimes\win10-$(Platform)\native\Microsoft.Management.Configuration.winmd" DestinationFolder="$(TargetDir)" />
|
||||
</Target>
|
||||
</Project>
|
||||
@@ -0,0 +1,50 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace WindowsPackageManager.Interop;
|
||||
|
||||
internal sealed class ClassModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the interface for the projected class type generated by CsWinRT
|
||||
/// </summary>
|
||||
public Type InterfaceType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the projected class type generated by CsWinRT
|
||||
/// </summary>
|
||||
public Type ProjectedClassType { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the clsids for each context (e.g. OutOfProcProd, OutOfProcDev)
|
||||
/// </summary>
|
||||
public IReadOnlyDictionary<ClsidContext, Guid> Clsids { get; init; }
|
||||
|
||||
/// <summary>
|
||||
/// Get CLSID based on the provided context
|
||||
/// </summary>
|
||||
/// <param name="context">Context</param>
|
||||
/// <returns>CLSID for the provided context.</returns>
|
||||
/// <exception cref="InvalidOperationException">Throw an exception if the clsid context is not available for the current instance.</exception>
|
||||
public Guid GetClsid(ClsidContext context)
|
||||
{
|
||||
if (!Clsids.TryGetValue(context, out var clsid))
|
||||
{
|
||||
throw new InvalidOperationException($"{ProjectedClassType.FullName} is not implemented in context {context}");
|
||||
}
|
||||
|
||||
return clsid;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get IID corresponding to the COM object
|
||||
/// </summary>
|
||||
/// <returns>IID.</returns>
|
||||
public Guid GetIid()
|
||||
{
|
||||
return InterfaceType.GUID;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Management.Deployment;
|
||||
|
||||
namespace WindowsPackageManager.Interop;
|
||||
|
||||
internal static class ClassesDefinition
|
||||
{
|
||||
private static Dictionary<Type, ClassModel> Classes { get; } = new()
|
||||
{
|
||||
[typeof(PackageManager)] = new()
|
||||
{
|
||||
ProjectedClassType = typeof(PackageManager),
|
||||
InterfaceType = typeof(IPackageManager),
|
||||
Clsids = new Dictionary<ClsidContext, Guid>()
|
||||
{
|
||||
[ClsidContext.Prod] = new Guid("C53A4F16-787E-42A4-B304-29EFFB4BF597"),
|
||||
[ClsidContext.Dev] = new Guid("74CB3139-B7C5-4B9E-9388-E6616DEA288C"),
|
||||
},
|
||||
},
|
||||
|
||||
[typeof(FindPackagesOptions)] = new()
|
||||
{
|
||||
ProjectedClassType = typeof(FindPackagesOptions),
|
||||
InterfaceType = typeof(IFindPackagesOptions),
|
||||
Clsids = new Dictionary<ClsidContext, Guid>()
|
||||
{
|
||||
[ClsidContext.Prod] = new Guid("572DED96-9C60-4526-8F92-EE7D91D38C1A"),
|
||||
[ClsidContext.Dev] = new Guid("1BD8FF3A-EC50-4F69-AEEE-DF4C9D3BAA96"),
|
||||
},
|
||||
},
|
||||
|
||||
[typeof(CreateCompositePackageCatalogOptions)] = new()
|
||||
{
|
||||
ProjectedClassType = typeof(CreateCompositePackageCatalogOptions),
|
||||
InterfaceType = typeof(ICreateCompositePackageCatalogOptions),
|
||||
Clsids = new Dictionary<ClsidContext, Guid>()
|
||||
{
|
||||
[ClsidContext.Prod] = new Guid("526534B8-7E46-47C8-8416-B1685C327D37"),
|
||||
[ClsidContext.Dev] = new Guid("EE160901-B317-4EA7-9CC6-5355C6D7D8A7"),
|
||||
},
|
||||
},
|
||||
|
||||
[typeof(InstallOptions)] = new()
|
||||
{
|
||||
ProjectedClassType = typeof(InstallOptions),
|
||||
InterfaceType = typeof(IInstallOptions),
|
||||
Clsids = new Dictionary<ClsidContext, Guid>()
|
||||
{
|
||||
[ClsidContext.Prod] = new Guid("1095F097-EB96-453B-B4E6-1613637F3B14"),
|
||||
[ClsidContext.Dev] = new Guid("44FE0580-62F7-44D4-9E91-AA9614AB3E86"),
|
||||
},
|
||||
},
|
||||
|
||||
[typeof(UninstallOptions)] = new()
|
||||
{
|
||||
ProjectedClassType = typeof(UninstallOptions),
|
||||
InterfaceType = typeof(IUninstallOptions),
|
||||
Clsids = new Dictionary<ClsidContext, Guid>()
|
||||
{
|
||||
[ClsidContext.Prod] = new Guid("E1D9A11E-9F85-4D87-9C17-2B93143ADB8D"),
|
||||
[ClsidContext.Dev] = new Guid("AA2A5C04-1AD9-46C4-B74F-6B334AD7EB8C"),
|
||||
},
|
||||
},
|
||||
|
||||
[typeof(PackageMatchFilter)] = new()
|
||||
{
|
||||
ProjectedClassType = typeof(PackageMatchFilter),
|
||||
InterfaceType = typeof(IPackageMatchFilter),
|
||||
Clsids = new Dictionary<ClsidContext, Guid>()
|
||||
{
|
||||
[ClsidContext.Prod] = new Guid("D02C9DAF-99DC-429C-B503-4E504E4AB000"),
|
||||
[ClsidContext.Dev] = new Guid("3F85B9F4-487A-4C48-9035-2903F8A6D9E8"),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Get CLSID based on the provided context for the specified type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Projected class type</typeparam>
|
||||
/// <param name="context">Context</param>
|
||||
/// <returns>CLSID for the provided context and type, or throw an exception if not found.</returns>
|
||||
/// <exception cref="InvalidOperationException">Throws an exception if type is not a project class.</exception>
|
||||
public static Guid GetClsid<T>(ClsidContext context)
|
||||
{
|
||||
ValidateType<T>();
|
||||
return Classes[typeof(T)].GetClsid(context);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get IID corresponding to the COM object
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Projected class type</typeparam>
|
||||
/// <returns>IID or throw an exception if not found.</returns>
|
||||
/// <exception cref="InvalidOperationException">Throws an exception if type is not a project class.</exception>
|
||||
public static Guid GetIid<T>()
|
||||
{
|
||||
ValidateType<T>();
|
||||
return Classes[typeof(T)].GetIid();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate that the provided type is defined.
|
||||
/// </summary>
|
||||
/// <param name="type">Projected class type</param>
|
||||
/// <exception cref="InvalidOperationException">Throws an exception if type is not a project class.</exception>
|
||||
private static void ValidateType<TType>()
|
||||
{
|
||||
if (!Classes.ContainsKey(typeof(TType)))
|
||||
{
|
||||
throw new InvalidOperationException($"{typeof(TType).Name} is not a projected class type.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
namespace WindowsPackageManager.Interop;
|
||||
|
||||
public enum ClsidContext
|
||||
{
|
||||
// Production CLSID Guids
|
||||
Prod,
|
||||
|
||||
// Development CLSID Guids
|
||||
Dev,
|
||||
}
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using WinRT;
|
||||
|
||||
namespace WindowsPackageManager.Interop;
|
||||
|
||||
/// <summary>
|
||||
/// Factory for creating winget COM objects using manual activation
|
||||
/// to have them in an elevated context.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This needs to be called from an elevated context, or the winget
|
||||
/// server will reject the connection.
|
||||
///
|
||||
/// The WinGetServerManualActivation_CreateInstance function used here is defined in
|
||||
/// https://github.com/microsoft/winget-cli/blob/master/src/WinGetServer/WinGetServerManualActivation_Client.cpp
|
||||
///
|
||||
/// This class is based on what the winget cmdlets do. See
|
||||
/// https://github.com/microsoft/winget-cli/blob/master/src/PowerShell/Microsoft.WinGet.Client/Helpers/ComObjectFactory.cs
|
||||
/// </remarks>
|
||||
public class WindowsPackageManagerElevatedFactory : WindowsPackageManagerFactory
|
||||
{
|
||||
// The only CLSID context supported by the DLL we call is Prod.
|
||||
// If we want to use Dev classes we have to use a Dev version of the DLL.
|
||||
public WindowsPackageManagerElevatedFactory()
|
||||
: base(ClsidContext.Prod)
|
||||
{
|
||||
}
|
||||
|
||||
protected override unsafe T CreateInstance<T>(Guid clsid, Guid iid)
|
||||
{
|
||||
void* pUnknown = null;
|
||||
|
||||
try
|
||||
{
|
||||
var hr = WinGetServerManualActivation_CreateInstance(in clsid, in iid, 0, out pUnknown);
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
return MarshalInterface<T>.FromAbi((IntPtr)pUnknown);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// CoCreateInstance and FromAbi both AddRef on the native object.
|
||||
// Release once to prevent memory leak.
|
||||
if (pUnknown is not null)
|
||||
{
|
||||
Marshal.Release((IntPtr)pUnknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[DllImport("winrtact.dll", ExactSpelling = true)]
|
||||
private static unsafe extern int WinGetServerManualActivation_CreateInstance(
|
||||
in Guid clsid,
|
||||
in Guid iid,
|
||||
uint flags,
|
||||
out void* instance);
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using Microsoft.Management.Deployment;
|
||||
|
||||
namespace WindowsPackageManager.Interop;
|
||||
|
||||
/// <summary>
|
||||
/// Factory class for creating WinGet COM objects.
|
||||
/// Details about each method can be found in the source IDL:
|
||||
/// https://github.com/microsoft/winget-cli/blob/master/src/Microsoft.Management.Deployment/PackageManager.idl
|
||||
/// </summary>
|
||||
public abstract class WindowsPackageManagerFactory
|
||||
{
|
||||
private readonly ClsidContext _clsidContext;
|
||||
|
||||
public WindowsPackageManagerFactory(ClsidContext clsidContext)
|
||||
{
|
||||
_clsidContext = clsidContext;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of the class <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Type <typeparamref name="T"/> must be one of the types defined in the winget COM API.
|
||||
/// Implementations of this method can assume that <paramref name="clsid"/> and <paramref name="iid"/>
|
||||
/// are the right GUIDs for the class in the given context.
|
||||
/// </remarks>
|
||||
protected abstract T CreateInstance<T>(Guid clsid, Guid iid);
|
||||
|
||||
public PackageManager CreatePackageManager() => CreateInstance<PackageManager>();
|
||||
|
||||
public FindPackagesOptions CreateFindPackagesOptions() => CreateInstance<FindPackagesOptions>();
|
||||
|
||||
public CreateCompositePackageCatalogOptions CreateCreateCompositePackageCatalogOptions() => CreateInstance<CreateCompositePackageCatalogOptions>();
|
||||
|
||||
public InstallOptions CreateInstallOptions() => CreateInstance<InstallOptions>();
|
||||
|
||||
public UninstallOptions CreateUninstallOptions() => CreateInstance<UninstallOptions>();
|
||||
|
||||
public PackageMatchFilter CreatePackageMatchFilter() => CreateInstance<PackageMatchFilter>();
|
||||
|
||||
/// <summary>
|
||||
/// Creates an instance of the class <typeparamref name="T"/>.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This is a helper for calling the derived class's <see cref="CreateInstance{T}(Guid, Guid)"/>
|
||||
/// method with the appropriate GUIDs.
|
||||
/// </remarks>
|
||||
private T CreateInstance<T>()
|
||||
{
|
||||
var clsid = ClassesDefinition.GetClsid<T>(_clsidContext);
|
||||
var iid = ClassesDefinition.GetIid<T>();
|
||||
return CreateInstance<T>(clsid, iid);
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using Windows.Win32;
|
||||
using Windows.Win32.System.Com;
|
||||
using WinRT;
|
||||
|
||||
namespace WindowsPackageManager.Interop;
|
||||
|
||||
public class WindowsPackageManagerStandardFactory : WindowsPackageManagerFactory
|
||||
{
|
||||
public WindowsPackageManagerStandardFactory(ClsidContext clsidContext = ClsidContext.Prod)
|
||||
: base(clsidContext)
|
||||
{
|
||||
}
|
||||
|
||||
protected override T CreateInstance<T>(Guid clsid, Guid iid)
|
||||
{
|
||||
var pUnknown = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
var hr = PInvoke.CoCreateInstance(clsid, null, CLSCTX.CLSCTX_LOCAL_SERVER, iid, out var result);
|
||||
Marshal.ThrowExceptionForHR(hr);
|
||||
pUnknown = Marshal.GetIUnknownForObject(result);
|
||||
return MarshalGeneric<T>.FromAbi(pUnknown);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// CoCreateInstance and FromAbi both AddRef on the native object.
|
||||
// Release once to prevent memory leak.
|
||||
if (pUnknown != IntPtr.Zero)
|
||||
{
|
||||
Marshal.Release(pUnknown);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user