commit bc9cb38e2ad941b6457d31f689f9dc912cc516b0
parent a9a02eddfe56fd1f81c17fea5e799c2831d69902
Author: JohnMcPMS <johnmcp@microsoft.com>
Date: Thu, 6 Apr 2023 11:13:53 -0700
Use in-proc winget in PowerShell module when running as SYSTEM (#3129)
This change uses the in-proc WinRT binaries and activation path when running as `SYSTEM` in the PowerShell module. It also makes `Assert-WinGetPackageManager` succeed as long as the OS version is high enough in that case.
There are two known caveats with this that could be addressed in a future change if needed:
1. These newly added dlls are still dependent on the VC runtime, and thus will not work unless it has been installed. This seems acceptable for development scenarios. For shipping a module without this dependency, we will need to build a statically linked binary, but only on the internal, release pipeline.
2. The code currently doesn't behave well in an STA thread, meaning that when used from `SYSTEM` the module requires running PowerShell with the MTA option.
Diffstat:
10 files changed, 302 insertions(+), 202 deletions(-)
diff --git a/.github/actions/spelling/expect.txt b/.github/actions/spelling/expect.txt
@@ -157,6 +157,7 @@ IHelp
iid
IISOn
inet
+inproc
installinprogress
installshield
instream
@@ -194,6 +195,7 @@ LPBYTE
LPCWSTR
LPDWORD
lpitemidlist
+LPW
maclachlan
LPSTR
LPWCH
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Commands/Common/BaseCommand.cs b/src/PowerShell/Microsoft.WinGet.Client/Commands/Common/BaseCommand.cs
@@ -21,9 +21,10 @@ namespace Microsoft.WinGet.Client.Commands.Common
public BaseCommand()
: base()
{
- if (Utilities.ExecutingAsSystem)
+ // The inproc COM API may deadlock on an STA thread.
+ if (Utilities.UsesInProcWinget && Utilities.ThreadIsSTA)
{
- throw new ExecuteAsSystemException();
+ throw new SingleThreadedApartmentException();
}
}
}
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Common/Utilities.cs b/src/PowerShell/Microsoft.WinGet.Client/Common/Utilities.cs
@@ -8,6 +8,7 @@ namespace Microsoft.WinGet.Client.Common
{
using System;
using System.Security.Principal;
+ using System.Threading;
/// <summary>
/// This class contains various helper methods for this project.
@@ -36,9 +37,30 @@ namespace Microsoft.WinGet.Client.Common
{
get
{
- WindowsIdentity identity = WindowsIdentity.GetCurrent();
- WindowsPrincipal principal = new (identity);
- return principal.IsInRole(WindowsBuiltInRole.SystemOperator);
+ return WindowsIdentity.GetCurrent().IsSystem;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current execution context will use in-proc winget.
+ /// </summary>
+ public static bool UsesInProcWinget
+ {
+ get
+ {
+ return ExecutingAsSystem;
+ }
+ }
+
+ /// <summary>
+ /// Gets a value indicating whether the current thread is executing as STA.
+ /// </summary>
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "Windows only API")]
+ public static bool ThreadIsSTA
+ {
+ get
+ {
+ return Thread.CurrentThread.GetApartmentState() == ApartmentState.STA;
}
}
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Common/WinGetIntegrity.cs b/src/PowerShell/Microsoft.WinGet.Client/Common/WinGetIntegrity.cs
@@ -26,6 +26,18 @@ namespace Microsoft.WinGet.Client.Common
/// <param name="expectedVersion">Expected version.</param>
public static void AssertWinGet(PSCmdlet psCmdlet, string expectedVersion)
{
+ // In-proc shouldn't have other dependencies and thus should be ok.
+ if (Utilities.UsesInProcWinget)
+ {
+ // Only check the OS version support for in-proc
+ if (!IsSupportedOSVersion())
+ {
+ throw new WinGetIntegrityException(IntegrityCategory.OsNotSupported);
+ }
+
+ return;
+ }
+
try
{
// Start by calling winget without its WindowsApp PFN path.
@@ -114,10 +126,8 @@ namespace Microsoft.WinGet.Client.Common
// Not under %LOCALAPPDATA%\\Microsoft\\WindowsApps\PFM\
- // Windows version has to be equal or newer than 10.0.17763.0
- var minWindowsVersion = new Version(10, 0, 17763, 0);
- var osVersion = Environment.OSVersion.Version;
- if (osVersion.CompareTo(minWindowsVersion) < 0)
+ // Check OS version
+ if (!IsSupportedOSVersion())
{
return IntegrityCategory.OsNotSupported;
}
@@ -143,5 +153,13 @@ namespace Microsoft.WinGet.Client.Common
// If we get here, we know the package is in the machine but not registered for the user.
return IntegrityCategory.AppInstallerNotRegistered;
}
+
+ private static bool IsSupportedOSVersion()
+ {
+ // Windows version has to be equal or newer than 10.0.17763.0
+ var minWindowsVersion = new Version(10, 0, 17763, 0);
+ var osVersion = Environment.OSVersion.Version;
+ return osVersion.CompareTo(minWindowsVersion) >= 0;
+ }
}
}
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Exceptions/ExecuteAsSystemException.cs b/src/PowerShell/Microsoft.WinGet.Client/Exceptions/ExecuteAsSystemException.cs
@@ -1,26 +0,0 @@
-// -----------------------------------------------------------------------------
-// <copyright file="ExecuteAsSystemException.cs" company="Microsoft Corporation">
-// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
-// </copyright>
-// -----------------------------------------------------------------------------
-
-namespace Microsoft.WinGet.Client.Exceptions
-{
- using System;
- using Microsoft.WinGet.Client.Properties;
-
- /// <summary>
- /// Executing as system is disabled.
- /// </summary>
- [Serializable]
- public class ExecuteAsSystemException : Exception
- {
- /// <summary>
- /// Initializes a new instance of the <see cref="ExecuteAsSystemException"/> class.
- /// </summary>
- public ExecuteAsSystemException()
- : base(Resources.ExecuteAsSystemExceptionMessage)
- {
- }
- }
-}
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Exceptions/SingleThreadedApartmentException.cs b/src/PowerShell/Microsoft.WinGet.Client/Exceptions/SingleThreadedApartmentException.cs
@@ -0,0 +1,27 @@
+// -----------------------------------------------------------------------------
+// <copyright file="SingleThreadedApartmentException.cs" company="Microsoft Corporation">
+// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
+// </copyright>
+// -----------------------------------------------------------------------------
+
+namespace Microsoft.WinGet.Client.Exceptions
+{
+ using System;
+ using System.Management.Automation;
+ using Microsoft.WinGet.Client.Properties;
+
+ /// <summary>
+ /// No package found.
+ /// </summary>
+ [Serializable]
+ public class SingleThreadedApartmentException : RuntimeException
+ {
+ /// <summary>
+ /// Initializes a new instance of the <see cref="SingleThreadedApartmentException"/> class.
+ /// </summary>
+ public SingleThreadedApartmentException()
+ : base(Resources.SingleThreadedApartmentNotSupportedMessage)
+ {
+ }
+ }
+}
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Helpers/ComObjectFactory.cs b/src/PowerShell/Microsoft.WinGet.Client/Helpers/ComObjectFactory.cs
@@ -1,154 +1,190 @@
-// -----------------------------------------------------------------------------
-// <copyright file="ComObjectFactory.cs" company="Microsoft Corporation">
-// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
-// </copyright>
-// -----------------------------------------------------------------------------
-
-namespace Microsoft.WinGet.Client.Factories
-{
- using System;
- using System.Runtime.InteropServices;
- using Microsoft.Management.Deployment;
- using Microsoft.WinGet.Client.Common;
- using Microsoft.WinGet.Client.Exceptions;
-
-#if NET
- using WinRT;
-#endif
-
- /// <summary>
- /// Constructs instances of classes from the <see cref="Management.Deployment" /> namespace.
- /// </summary>
- public class ComObjectFactory
- {
-#if USE_PROD_CLSIDS
- private static readonly Guid PackageManagerClsid = Guid.Parse("C53A4F16-787E-42A4-B304-29EFFB4BF597");
- private static readonly Guid FindPackagesOptionsClsid = Guid.Parse("572DED96-9C60-4526-8F92-EE7D91D38C1A");
- private static readonly Guid CreateCompositePackageCatalogOptionsClsid = Guid.Parse("526534B8-7E46-47C8-8416-B1685C327D37");
- private static readonly Guid InstallOptionsClsid = Guid.Parse("1095F097-EB96-453B-B4E6-1613637F3B14");
- private static readonly Guid UninstallOptionsClsid = Guid.Parse("E1D9A11E-9F85-4D87-9C17-2B93143ADB8D");
- private static readonly Guid PackageMatchFilterClsid = Guid.Parse("D02C9DAF-99DC-429C-B503-4E504E4AB000");
-#else
- private static readonly Guid PackageManagerClsid = Guid.Parse("74CB3139-B7C5-4B9E-9388-E6616DEA288C");
- private static readonly Guid FindPackagesOptionsClsid = Guid.Parse("1BD8FF3A-EC50-4F69-AEEE-DF4C9D3BAA96");
- private static readonly Guid CreateCompositePackageCatalogOptionsClsid = Guid.Parse("EE160901-B317-4EA7-9CC6-5355C6D7D8A7");
- private static readonly Guid InstallOptionsClsid = Guid.Parse("44FE0580-62F7-44D4-9E91-AA9614AB3E86");
- private static readonly Guid UninstallOptionsClsid = Guid.Parse("AA2A5C04-1AD9-46C4-B74F-6B334AD7EB8C");
- private static readonly Guid PackageMatchFilterClsid = Guid.Parse("3F85B9F4-487A-4C48-9035-2903F8A6D9E8");
-#endif
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
- private static readonly Type PackageManagerType = Type.GetTypeFromCLSID(PackageManagerClsid);
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
- private static readonly Type FindPackagesOptionsType = Type.GetTypeFromCLSID(FindPackagesOptionsClsid);
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
- private static readonly Type CreateCompositePackageCatalogOptionsType = Type.GetTypeFromCLSID(CreateCompositePackageCatalogOptionsClsid);
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
- private static readonly Type InstallOptionsType = Type.GetTypeFromCLSID(InstallOptionsClsid);
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
- private static readonly Type UninstallOptionsType = Type.GetTypeFromCLSID(UninstallOptionsClsid);
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
- private static readonly Type PackageMatchFilterType = Type.GetTypeFromCLSID(PackageMatchFilterClsid);
-
- private static readonly Guid PackageManagerIid = Guid.Parse("B375E3B9-F2E0-5C93-87A7-B67497F7E593");
- private static readonly Guid FindPackagesOptionsIid = Guid.Parse("A5270EDD-7DA7-57A3-BACE-F2593553561F");
- private static readonly Guid CreateCompositePackageCatalogOptionsIid = Guid.Parse("21ABAA76-089D-51C5-A745-C85EEFE70116");
- private static readonly Guid InstallOptionsIid = Guid.Parse("6EE9DB69-AB48-5E72-A474-33A924CD23B3");
- private static readonly Guid UninstallOptionsIid = Guid.Parse("3EBC67F0-8339-594B-8A42-F90B69D02BBE");
- private static readonly Guid PackageMatchFilterIid = Guid.Parse("D981ECA3-4DE5-5AD7-967A-698C7D60FC3B");
-
- /// <summary>
- /// Creates an instance of the <see cref="PackageManager" /> class.
- /// </summary>
- /// <returns>A <see cref="PackageManager" /> instance.</returns>
- public virtual PackageManager CreatePackageManager()
- {
- return Create<PackageManager>(PackageManagerType, PackageManagerIid);
- }
-
- /// <summary>
- /// Creates an instance of the <see cref="FindPackagesOptions" /> class.
- /// </summary>
- /// <returns>A <see cref="FindPackagesOptions" /> instance.</returns>
- public virtual FindPackagesOptions CreateFindPackagesOptions()
- {
- return Create<FindPackagesOptions>(FindPackagesOptionsType, FindPackagesOptionsIid);
- }
-
- /// <summary>
- /// Creates an instance of the <see cref="CreateCompositePackageCatalogOptions" /> class.
- /// </summary>
- /// <returns>A <see cref="CreateCompositePackageCatalogOptions" /> instance.</returns>
- public virtual CreateCompositePackageCatalogOptions CreateCreateCompositePackageCatalogOptions()
- {
- return Create<CreateCompositePackageCatalogOptions>(CreateCompositePackageCatalogOptionsType, CreateCompositePackageCatalogOptionsIid);
- }
-
- /// <summary>
- /// Creates an instance of the <see cref="InstallOptions" /> class.
- /// </summary>
- /// <returns>An <see cref="InstallOptions" /> instance.</returns>
- public virtual InstallOptions CreateInstallOptions()
- {
- return Create<InstallOptions>(InstallOptionsType, InstallOptionsIid);
- }
-
- /// <summary>
- /// Creates an instance of the <see cref="UninstallOptions" /> class.
- /// </summary>
- /// <returns>A <see cref="UninstallOptions" /> instance.</returns>
- public virtual UninstallOptions CreateUninstallOptions()
- {
- return Create<UninstallOptions>(UninstallOptionsType, UninstallOptionsIid);
- }
-
- /// <summary>
- /// Creates an instance of the <see cref="PackageMatchFilter" /> class.
- /// </summary>
- /// <returns>A <see cref="PackageMatchFilter" /> instance.</returns>
- public virtual PackageMatchFilter CreatePackageMatchFilter()
- {
- return Create<PackageMatchFilter>(PackageMatchFilterType, PackageMatchFilterIid);
- }
-
- [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
- private static T Create<T>(Type type, in Guid iid)
- {
- object instance = null;
-
- if (Utilities.ExecutingAsAdministrator)
- {
- int hr = WinGetServerManualActivation_CreateInstance(type.GUID, iid, 0, out instance);
-
- if (hr < 0)
- {
- if (hr == ErrorCode.FileNotFound)
- {
- throw new WinGetIntegrityException(IntegrityCategory.AppInstallerNotInstalled);
- }
- else
- {
- throw new COMException($"Failed to create instance: {hr}", hr);
- }
- }
- }
- else
- {
- instance = Activator.CreateInstance(type);
- }
-
-#if NET
- IntPtr pointer = Marshal.GetIUnknownForObject(instance);
- return MarshalInterface<T>.FromAbi(pointer);
-#else
- return (T)instance;
-#endif
- }
-
- [DllImport("winrtact.dll", EntryPoint = "WinGetServerManualActivation_CreateInstance", ExactSpelling = true, PreserveSig = true)]
- private static extern int WinGetServerManualActivation_CreateInstance(
- [In, MarshalAs(UnmanagedType.LPStruct)] Guid clsid,
- [In, MarshalAs(UnmanagedType.LPStruct)] Guid iid,
- uint flags,
- [Out, MarshalAs(UnmanagedType.IUnknown)] out object instance);
- }
-}
+// -----------------------------------------------------------------------------
+// <copyright file="ComObjectFactory.cs" company="Microsoft Corporation">
+// Copyright (c) Microsoft Corporation. Licensed under the MIT License.
+// </copyright>
+// -----------------------------------------------------------------------------
+
+namespace Microsoft.WinGet.Client.Factories
+{
+ using System;
+ using System.IO;
+ using System.Reflection;
+ using System.Runtime.InteropServices;
+ using Microsoft.Management.Deployment;
+ using Microsoft.WinGet.Client.Common;
+ using Microsoft.WinGet.Client.Exceptions;
+ using Windows.Networking.Sockets;
+
+#if NET
+ using WinRT;
+#endif
+
+ /// <summary>
+ /// Constructs instances of classes from the <see cref="Management.Deployment" /> namespace.
+ /// </summary>
+ public class ComObjectFactory
+ {
+#if USE_PROD_CLSIDS
+ private static readonly Guid PackageManagerClsid = Guid.Parse("C53A4F16-787E-42A4-B304-29EFFB4BF597");
+ private static readonly Guid FindPackagesOptionsClsid = Guid.Parse("572DED96-9C60-4526-8F92-EE7D91D38C1A");
+ private static readonly Guid CreateCompositePackageCatalogOptionsClsid = Guid.Parse("526534B8-7E46-47C8-8416-B1685C327D37");
+ private static readonly Guid InstallOptionsClsid = Guid.Parse("1095F097-EB96-453B-B4E6-1613637F3B14");
+ private static readonly Guid UninstallOptionsClsid = Guid.Parse("E1D9A11E-9F85-4D87-9C17-2B93143ADB8D");
+ private static readonly Guid PackageMatchFilterClsid = Guid.Parse("D02C9DAF-99DC-429C-B503-4E504E4AB000");
+#else
+ private static readonly Guid PackageManagerClsid = Guid.Parse("74CB3139-B7C5-4B9E-9388-E6616DEA288C");
+ private static readonly Guid FindPackagesOptionsClsid = Guid.Parse("1BD8FF3A-EC50-4F69-AEEE-DF4C9D3BAA96");
+ private static readonly Guid CreateCompositePackageCatalogOptionsClsid = Guid.Parse("EE160901-B317-4EA7-9CC6-5355C6D7D8A7");
+ private static readonly Guid InstallOptionsClsid = Guid.Parse("44FE0580-62F7-44D4-9E91-AA9614AB3E86");
+ private static readonly Guid UninstallOptionsClsid = Guid.Parse("AA2A5C04-1AD9-46C4-B74F-6B334AD7EB8C");
+ private static readonly Guid PackageMatchFilterClsid = Guid.Parse("3F85B9F4-487A-4C48-9035-2903F8A6D9E8");
+#endif
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
+ private static readonly Type PackageManagerType = Type.GetTypeFromCLSID(PackageManagerClsid);
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
+ private static readonly Type FindPackagesOptionsType = Type.GetTypeFromCLSID(FindPackagesOptionsClsid);
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
+ private static readonly Type CreateCompositePackageCatalogOptionsType = Type.GetTypeFromCLSID(CreateCompositePackageCatalogOptionsClsid);
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
+ private static readonly Type InstallOptionsType = Type.GetTypeFromCLSID(InstallOptionsClsid);
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
+ private static readonly Type UninstallOptionsType = Type.GetTypeFromCLSID(UninstallOptionsClsid);
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
+ private static readonly Type PackageMatchFilterType = Type.GetTypeFromCLSID(PackageMatchFilterClsid);
+
+ private static readonly Guid PackageManagerIid = Guid.Parse("B375E3B9-F2E0-5C93-87A7-B67497F7E593");
+ private static readonly Guid FindPackagesOptionsIid = Guid.Parse("A5270EDD-7DA7-57A3-BACE-F2593553561F");
+ private static readonly Guid CreateCompositePackageCatalogOptionsIid = Guid.Parse("21ABAA76-089D-51C5-A745-C85EEFE70116");
+ private static readonly Guid InstallOptionsIid = Guid.Parse("6EE9DB69-AB48-5E72-A474-33A924CD23B3");
+ private static readonly Guid UninstallOptionsIid = Guid.Parse("3EBC67F0-8339-594B-8A42-F90B69D02BBE");
+ private static readonly Guid PackageMatchFilterIid = Guid.Parse("D981ECA3-4DE5-5AD7-967A-698C7D60FC3B");
+
+ /// <summary>
+ /// Initializes static members of the <see cref="ComObjectFactory"/> class.
+ /// </summary>
+ static ComObjectFactory()
+ {
+ if (Utilities.UsesInProcWinget)
+ {
+ PackageManagerSettings settings = new PackageManagerSettings();
+ settings.SetCallerIdentifier("PowerShellInProc");
+ }
+ }
+
+ /// <summary>
+ /// Creates an instance of the <see cref="PackageManager" /> class.
+ /// </summary>
+ /// <returns>A <see cref="PackageManager" /> instance.</returns>
+ public virtual PackageManager CreatePackageManager()
+ {
+ return Create<PackageManager>(PackageManagerType, PackageManagerIid);
+ }
+
+ /// <summary>
+ /// Creates an instance of the <see cref="FindPackagesOptions" /> class.
+ /// </summary>
+ /// <returns>A <see cref="FindPackagesOptions" /> instance.</returns>
+ public virtual FindPackagesOptions CreateFindPackagesOptions()
+ {
+ return Create<FindPackagesOptions>(FindPackagesOptionsType, FindPackagesOptionsIid);
+ }
+
+ /// <summary>
+ /// Creates an instance of the <see cref="CreateCompositePackageCatalogOptions" /> class.
+ /// </summary>
+ /// <returns>A <see cref="CreateCompositePackageCatalogOptions" /> instance.</returns>
+ public virtual CreateCompositePackageCatalogOptions CreateCreateCompositePackageCatalogOptions()
+ {
+ return Create<CreateCompositePackageCatalogOptions>(CreateCompositePackageCatalogOptionsType, CreateCompositePackageCatalogOptionsIid);
+ }
+
+ /// <summary>
+ /// Creates an instance of the <see cref="InstallOptions" /> class.
+ /// </summary>
+ /// <returns>An <see cref="InstallOptions" /> instance.</returns>
+ public virtual InstallOptions CreateInstallOptions()
+ {
+ return Create<InstallOptions>(InstallOptionsType, InstallOptionsIid);
+ }
+
+ /// <summary>
+ /// Creates an instance of the <see cref="UninstallOptions" /> class.
+ /// </summary>
+ /// <returns>A <see cref="UninstallOptions" /> instance.</returns>
+ public virtual UninstallOptions CreateUninstallOptions()
+ {
+ return Create<UninstallOptions>(UninstallOptionsType, UninstallOptionsIid);
+ }
+
+ /// <summary>
+ /// Creates an instance of the <see cref="PackageMatchFilter" /> class.
+ /// </summary>
+ /// <returns>A <see cref="PackageMatchFilter" /> instance.</returns>
+ public virtual PackageMatchFilter CreatePackageMatchFilter()
+ {
+ return Create<PackageMatchFilter>(PackageMatchFilterType, PackageMatchFilterIid);
+ }
+
+ [System.Diagnostics.CodeAnalysis.SuppressMessage("Interoperability", "CA1416:Validate platform compatibility", Justification = "COM only usage.")]
+ private static T Create<T>(Type type, in Guid iid)
+ where T : new()
+ {
+ if (Utilities.UsesInProcWinget)
+ {
+ string executingAssemblyLocation = Assembly.GetExecutingAssembly().Location;
+ string executingAssemblyDirectory = Path.GetDirectoryName(executingAssemblyLocation);
+ SetDllDirectoryW(executingAssemblyDirectory);
+
+ try
+ {
+ return new T();
+ }
+ finally
+ {
+ SetDllDirectoryW(null);
+ }
+ }
+
+ object instance = null;
+
+ if (Utilities.ExecutingAsAdministrator)
+ {
+ int hr = WinGetServerManualActivation_CreateInstance(type.GUID, iid, 0, out instance);
+
+ if (hr < 0)
+ {
+ if (hr == ErrorCode.FileNotFound)
+ {
+ throw new WinGetIntegrityException(IntegrityCategory.AppInstallerNotInstalled);
+ }
+ else
+ {
+ throw new COMException($"Failed to create instance: {hr}", hr);
+ }
+ }
+ }
+ else
+ {
+ instance = Activator.CreateInstance(type);
+ }
+
+#if NET
+ IntPtr pointer = Marshal.GetIUnknownForObject(instance);
+ return MarshalInterface<T>.FromAbi(pointer);
+#else
+ return (T)instance;
+#endif
+ }
+
+ [DllImport("winrtact.dll", EntryPoint = "WinGetServerManualActivation_CreateInstance", ExactSpelling = true, PreserveSig = true)]
+ private static extern int WinGetServerManualActivation_CreateInstance(
+ [In, MarshalAs(UnmanagedType.LPStruct)] Guid clsid,
+ [In, MarshalAs(UnmanagedType.LPStruct)] Guid iid,
+ uint flags,
+ [Out, MarshalAs(UnmanagedType.IUnknown)] out object instance);
+
+ [DllImport("kernel32.dll", SetLastError = true)]
+ [return: MarshalAs(UnmanagedType.Bool)]
+ private static extern bool SetDllDirectoryW([MarshalAs(UnmanagedType.LPWStr)] string directory);
+ }
+}
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Microsoft.WinGet.Client.csproj b/src/PowerShell/Microsoft.WinGet.Client/Microsoft.WinGet.Client.csproj
@@ -47,6 +47,14 @@
<OutputItemType>Content</OutputItemType>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</ProjectReference>
+ <ProjectReference Include="..\..\Microsoft.Management.Deployment.InProc\Microsoft.Management.Deployment.InProc.vcxproj">
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </ProjectReference>
+ <ProjectReference Include="..\..\WindowsPackageManager\WindowsPackageManager.vcxproj">
+ <OutputItemType>Content</OutputItemType>
+ <CopyToOutputDirectory>Always</CopyToOutputDirectory>
+ </ProjectReference>
</ItemGroup>
<PropertyGroup>
@@ -159,4 +167,15 @@
<Copy SourceFiles="@(DesktopBinaries)" DestinationFolder="$(PowerShellModuleLibDirectory)\$(DesktopFramework)\$(Platform)\%(RecursiveDir)" />
</Target>
+ <!-- Rename Microsoft.Management.Deployment.InProc.dll to Microsoft.Management.Deployment.dll -->
+ <Target Name="RenameMicrosoftManagementDeployment" AfterTargets="AfterBuild">
+ <ItemGroup>
+ <RenameModuleFiles Include="$(PowerShellModuleLibDirectory)\**\Microsoft.Management.Deployment.InProc.dll">
+ <NewName>Microsoft.Management.Deployment.dll</NewName>
+ </RenameModuleFiles>
+ </ItemGroup>
+ <Message Importance="high" Text="Renaming file '%(RenameModuleFiles.Identity)' to '$(PowerShellModuleLibDirectory)\%(RenameModuleFiles.RecursiveDir)\%(RenameModuleFiles.NewName)'" />
+ <Move SourceFiles="%(RenameModuleFiles.Identity)" DestinationFiles="$(PowerShellModuleLibDirectory)\%(RenameModuleFiles.RecursiveDir)\%(RenameModuleFiles.NewName)" />
+ </Target>
+
</Project>
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Properties/Resources.Designer.cs b/src/PowerShell/Microsoft.WinGet.Client/Properties/Resources.Designer.cs
@@ -79,15 +79,6 @@ namespace Microsoft.WinGet.Client.Properties {
}
/// <summary>
- /// Looks up a localized string similar to This cmdlet is currently disabled for SYSTEM..
- /// </summary>
- internal static string ExecuteAsSystemExceptionMessage {
- get {
- return ResourceManager.GetString("ExecuteAsSystemExceptionMessage", resourceCulture);
- }
- }
-
- /// <summary>
/// Looks up a localized string similar to An error occurred while searching for packages: {0}.
/// </summary>
internal static string FindPackagesExceptionMessage {
@@ -151,7 +142,7 @@ namespace Microsoft.WinGet.Client.Properties {
}
/// <summary>
- /// Looks up a localized string similar to The Windows Package Manager requires at least Version 1809 (October 2018 Update)..
+ /// Looks up a localized string similar to The Windows Package Manager requires Windows Version 1809 (October 2018 Update) or later..
/// </summary>
internal static string IntegrityOsNotSupportedMessage {
get {
@@ -241,6 +232,15 @@ namespace Microsoft.WinGet.Client.Properties {
}
/// <summary>
+ /// Looks up a localized string similar to Single threaded apartment (STA) is not currently supported in this context; run PowerShell in Multi-threaded apartment mode (MTA)..
+ /// </summary>
+ internal static string SingleThreadedApartmentNotSupportedMessage {
+ get {
+ return ResourceManager.GetString("SingleThreadedApartmentNotSupportedMessage", resourceCulture);
+ }
+ }
+
+ /// <summary>
/// Looks up a localized string similar to User settings file is invalid..
/// </summary>
internal static string UserSettingsReadException {
diff --git a/src/PowerShell/Microsoft.WinGet.Client/Properties/Resources.resx b/src/PowerShell/Microsoft.WinGet.Client/Properties/Resources.resx
@@ -121,9 +121,6 @@
<value>No source matches the given value: {0}</value>
<comment>{Locked="{0}"} {0} - The name of the source that was not found.</comment>
</data>
- <data name="ExecuteAsSystemExceptionMessage" xml:space="preserve">
- <value>This cmdlet is currently disabled for SYSTEM.</value>
- </data>
<data name="FindPackagesExceptionMessage" xml:space="preserve">
<value>An error occurred while searching for packages: {0}</value>
<comment>{Locked="{0}"} {0} - A string representation of the error status returned by the catalog.</comment>
@@ -203,4 +200,8 @@
<value>The installed winget version doesn't match the expectation. Installer version '{0}' Expected version '{1}'</value>
<comment>{Locked="{0}","{1}"} {0} - The winget current installed winget version. {1} - The expected winget version.</comment>
</data>
+ <data name="SingleThreadedApartmentNotSupportedMessage" xml:space="preserve">
+ <value>Single threaded apartment (STA) is not currently supported in this context; run PowerShell in Multi-threaded apartment mode (MTA).</value>
+ <comment>{Locked="STA","MTA"}</comment>
+ </data>
</root>
\ No newline at end of file