From 693ab67831e5b5b3d26544ff7260d674c0be3b43 Mon Sep 17 00:00:00 2001 From: Yu Leng <42196638+moooyo@users.noreply.github.com> Date: Tue, 3 Jun 2025 14:24:13 +0800 Subject: [PATCH] [cmdpal][AOT] make some built-in extensions able to be published with native AOT enabled (#39802) ## Summary of the Pull Request Base on my test, some built-in extensions can be published with native AOT enabled with a little changes. (see this branch: https://github.com/microsoft/PowerToys/pull/39605). 1. SystemCommands: no change need. Removed some unused code. 2. WinGet: disable marshalling. and do a little changes in CreateInstance. 3. WindowWalker: use source generation to call CoCreateInstance. 4. WindowsTerminal: use source generation to call IApplicationActivationManager interface. ## PR Checklist - [x] **Closes:** #39869 - [x] **Communication:** I've discussed this with core contributors already. If work hasn't been agreed, this work might be rejected - [x] **Tests:** Added/updated and all pass - [x] **Localization:** All end user facing strings can be localized - [ ] **Dev docs:** Added/updated - [ ] **New binaries:** Added on the required places - [ ] [JSON for signing](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ESRPSigning_core.json) for new binaries - [ ] [WXS for installer](https://github.com/microsoft/PowerToys/blob/main/installer/PowerToysSetup/Product.wxs) for new binaries and localization folder - [ ] [YML for CI pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/ci/templates/build-powertoys-steps.yml) for new test projects - [ ] [YML for signed pipeline](https://github.com/microsoft/PowerToys/blob/main/.pipelines/release.yml) - [ ] **Documentation updated:** If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/windows-uwp/tree/docs/hub/powertoys) and link it here: #xxx ## Detailed Description of the Pull Request / Additional comments ## Validation Steps Performed --------- Co-authored-by: Yu Leng --- .github/actions/spell-check/expect.txt | 1 + .../Helpers/Native.cs | 144 ------------------ .../Microsoft.CmdPal.Ext.WinGet.csproj | 5 + .../NativeMethods.json | 7 + .../WindowsPackageManagerStandardFactory.cs | 29 ++-- .../Helpers/IVirtualDesktopManager.cs | 13 +- .../Helpers/NativeMethods.cs | 68 ++------- .../Helpers/VirtualDesktopHelper.cs | 27 +++- .../Commands/LaunchProfileAsAdminCommand.cs | 28 ++-- .../Commands/LaunchProfileCommand.cs | 27 ++-- .../Helpers/ApplicationActivationManager.cs | 24 --- .../Helpers/IApplicationActivationManager.cs | 12 +- .../Helpers/NativeHelpers.cs | 32 ++++ 13 files changed, 142 insertions(+), 275 deletions(-) delete mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Native.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/NativeMethods.json delete mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs create mode 100644 src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/NativeHelpers.cs diff --git a/.github/actions/spell-check/expect.txt b/.github/actions/spell-check/expect.txt index f9d35feab1..ad79e2e8ca 100644 --- a/.github/actions/spell-check/expect.txt +++ b/.github/actions/spell-check/expect.txt @@ -1995,3 +1995,4 @@ culori Evercoder LCh CIELCh +CLSCTXINPROCALL \ No newline at end of file diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Native.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Native.cs deleted file mode 100644 index 3daf2a4be4..0000000000 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.System/Helpers/Native.cs +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Diagnostics.CodeAnalysis; -using System.Runtime.InteropServices; - -namespace Microsoft.CmdPal.Ext.System.Helpers; - -[SuppressMessage("Interoperability", "CA1401:P/Invokes should not be visible", Justification = "We want plugins to share this NativeMethods class, instead of each one creating its own.")] -public sealed class Native -{ - public enum HRESULT : uint - { - /// - /// Operation successful. - /// - S_OK = 0x00000000, - - /// - /// Operation successful. (negative condition/no operation) - /// - S_FALSE = 0x00000001, - - /// - /// Not implemented. - /// - E_NOTIMPL = 0x80004001, - - /// - /// No such interface supported. - /// - E_NOINTERFACE = 0x80004002, - - /// - /// Pointer that is not valid. - /// - E_POINTER = 0x80004003, - - /// - /// Operation aborted. - /// - E_ABORT = 0x80004004, - - /// - /// Unspecified failure. - /// - E_FAIL = 0x80004005, - - /// - /// Unexpected failure. - /// - E_UNEXPECTED = 0x8000FFFF, - - /// - /// General access denied error. - /// - E_ACCESSDENIED = 0x80070005, - - /// - /// Handle that is not valid. - /// - E_HANDLE = 0x80070006, - - /// - /// Failed to allocate necessary memory. - /// - E_OUTOFMEMORY = 0x8007000E, - - /// - /// One or more arguments are not valid. - /// - E_INVALIDARG = 0x80070057, - - /// - /// The operation was canceled by the user. (Error source 7 means Win32.) - /// - /// - /// - E_CANCELLED = 0x800704C7, - } - - public static class ShellItemTypeConstants - { - /// - /// Guid for type IShellItem. - /// - public static readonly Guid ShellItemGuid = new("43826d1e-e718-42ee-bc55-a1e261c37bfe"); - - /// - /// Guid for type IShellItem2. - /// - public static readonly Guid ShellItem2Guid = new("7E9FB0D3-919F-4307-AB2E-9B1860310C93"); - } - - /// - /// The following are ShellItem DisplayName types. - /// - [Flags] - public enum SIGDN : uint - { - NORMALDISPLAY = 0, - PARENTRELATIVEPARSING = 0x80018001, - PARENTRELATIVEFORADDRESSBAR = 0x8001c001, - DESKTOPABSOLUTEPARSING = 0x80028000, - PARENTRELATIVEEDITING = 0x80031001, - DESKTOPABSOLUTEEDITING = 0x8004c000, - FILESYSPATH = 0x80058000, - URL = 0x80068000, - } - - [ComImport] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")] - public interface IShellItem - { - void BindToHandler( - nint pbc, - [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, - [MarshalAs(UnmanagedType.LPStruct)] Guid riid, - out nint ppv); - - void GetParent(out IShellItem ppsi); - - void GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName); - - void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs); - - void Compare(IShellItem psi, uint hint, out int piOrder); - } - - /// - /// see all STGM values - /// - [Flags] - public enum STGM : long - { - READ = 0x00000000L, - WRITE = 0x00000001L, - READWRITE = 0x00000002L, - CREATE = 0x00001000L, - } -} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj index 7c5c6d2dd3..2f9da761d2 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/Microsoft.CmdPal.Ext.WinGet.csproj @@ -32,6 +32,11 @@ + + + + + diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/NativeMethods.json b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/NativeMethods.json new file mode 100644 index 0000000000..02fff599f2 --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/NativeMethods.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://aka.ms/CsWin32.schema.json", + "allowMarshaling": false, + "comInterop": { + "preserveSigMethods": [ "*" ] + } +} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs index d8b6064a86..677f688ac6 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WinGet/WindowsPackageManager.Interop/WindowsPackageManagerStandardFactory.cs @@ -20,20 +20,25 @@ public class WindowsPackageManagerStandardFactory : WindowsPackageManagerFactory protected override T CreateInstance(Guid clsid, Guid iid) { var pUnknown = IntPtr.Zero; - try + unsafe { - var hr = PInvoke.CoCreateInstance(clsid, null, CLSCTX.CLSCTX_ALL, iid, out var result); - Marshal.ThrowExceptionForHR(hr); - pUnknown = Marshal.GetIUnknownForObject(result); - return MarshalGeneric.FromAbi(pUnknown); - } - finally - { - // CoCreateInstance and FromAbi both AddRef on the native object. - // Release once to prevent memory leak. - if (pUnknown != IntPtr.Zero) + try { - Marshal.Release(pUnknown); + var hr = PInvoke.CoCreateInstance(clsid, null, CLSCTX.CLSCTX_ALL, iid, out var result); + Marshal.ThrowExceptionForHR(hr); + + pUnknown = new IntPtr(result); + + return MarshalGeneric.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); + } } } } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs index 070e24cc26..75170a56cc 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/IVirtualDesktopManager.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers; @@ -11,18 +12,16 @@ namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers; /// Interface for accessing Virtual Desktop Manager. /// Code used from /// -[ComImport] -[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] +[GeneratedComInterface] [Guid("a5cd92ff-29be-454c-8d04-d82879fb3f1b")] -[System.Security.SuppressUnmanagedCodeSecurity] -internal interface IVirtualDesktopManager +public partial interface IVirtualDesktopManager { [PreserveSig] - int IsWindowOnCurrentVirtualDesktop([In] IntPtr hTopLevelWindow, [Out] out int onCurrentDesktop); + int IsWindowOnCurrentVirtualDesktop(IntPtr hTopLevelWindow, out int onCurrentDesktop); [PreserveSig] - int GetWindowDesktopId([In] IntPtr hTopLevelWindow, [Out] out Guid desktop); + int GetWindowDesktopId(IntPtr hTopLevelWindow, out Guid desktop); [PreserveSig] - int MoveWindowToDesktop([In] IntPtr hTopLevelWindow, [MarshalAs(UnmanagedType.LPStruct)][In] Guid desktop); + int MoveWindowToDesktop(IntPtr hTopLevelWindow, ref Guid desktop); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs index e60cb262fe..21b2f7910c 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/NativeMethods.cs @@ -13,7 +13,7 @@ using SuppressMessageAttribute = System.Diagnostics.CodeAnalysis.SuppressMessage namespace Microsoft.CmdPal.Ext.WindowWalker.Helpers; [SuppressMessage("Interoperability", "CA1401:P/Invokes should not be visible", Justification = "We want plugins to share this NativeMethods class, instead of each one creating its own.")] -public static class NativeMethods +public static partial class NativeMethods { [DllImport("user32.dll", CharSet = CharSet.Unicode)] public static extern int EnumWindows(EnumWindowsProc callPtr, IntPtr lParam); @@ -99,31 +99,14 @@ public static class NativeMethods [return: MarshalAs(UnmanagedType.Bool)] public static extern bool GetFirmwareType(ref FirmwareType FirmwareType); - [DllImport("user32.dll")] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool ExitWindowsEx(uint uFlags, uint dwReason); - - [DllImport("user32")] - public static extern void LockWorkStation(); - - [DllImport("Powrprof.dll", CharSet = CharSet.Auto, ExactSpelling = true)] - [return: MarshalAs(UnmanagedType.Bool)] - public static extern bool SetSuspendState(bool hibernate, bool forceCritical, bool disableWakeEvent); - - [DllImport("Shell32.dll", CharSet = CharSet.Unicode)] - public static extern uint SHEmptyRecycleBin(IntPtr hWnd, uint dwFlags); - - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] - public static extern HRESULT SHLoadIndirectString(string pszSource, StringBuilder pszOutBuf, uint cchOutBuf, IntPtr ppvReserved); - - [DllImport("shlwapi.dll", CharSet = CharSet.Unicode)] - public static extern HRESULT SHCreateStreamOnFileEx(string fileName, STGM grfMode, uint attributes, bool create, System.Runtime.InteropServices.ComTypes.IStream reserved, out System.Runtime.InteropServices.ComTypes.IStream stream); - - [DllImport("shell32.dll", CharSet = CharSet.Unicode, SetLastError = true)] - public static extern int SHCreateItemFromParsingName([MarshalAs(UnmanagedType.LPWStr)] string path, IntPtr pbc, ref Guid riid, [MarshalAs(UnmanagedType.Interface)] out IShellItem shellItem); - - [DllImport("rpcrt4.dll")] - public static extern int UuidCreateSequential(out GUIDDATA Uuid); + [LibraryImport("ole32.dll")] + [return: MarshalAs(UnmanagedType.U4)] + public static partial uint CoCreateInstance( + ref Guid rclsid, + IntPtr pUnkOuter, + uint dwClsContext, + ref Guid riid, + out IntPtr rReturnedComObject); } [SuppressMessage("StyleCop.CSharp.NamingRules", "SA1310:Field names should not contain underscore", Justification = "These are the names used by win32.")] @@ -161,19 +144,6 @@ public static class Win32Constants public const int RPC_S_UUID_LOCAL_ONLY = 0x720; } -public static class ShellItemTypeConstants -{ - /// - /// Guid for type IShellItem. - /// - public static readonly Guid ShellItemGuid = new("43826d1e-e718-42ee-bc55-a1e261c37bfe"); - - /// - /// Guid for type IShellItem2. - /// - public static readonly Guid ShellItem2Guid = new("7E9FB0D3-919F-4307-AB2E-9B1860310C93"); -} - public enum HRESULT : uint { /// @@ -1124,26 +1094,6 @@ public enum ExtendedWindowStyles : uint WS_EX_NOACTIVATE = 0x8000000, } -[ComImport] -[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -[Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")] -public interface IShellItem -{ - void BindToHandler( - IntPtr pbc, - [MarshalAs(UnmanagedType.LPStruct)] Guid bhid, - [MarshalAs(UnmanagedType.LPStruct)] Guid riid, - out IntPtr ppv); - - void GetParent(out IShellItem ppsi); - - void GetDisplayName(SIGDN sigdnName, [MarshalAs(UnmanagedType.LPWStr)] out string ppszName); - - void GetAttributes(uint sfgaoMask, out uint psfgaoAttribs); - - void Compare(IShellItem psi, uint hint, out int piOrder); -} - /// /// The following are ShellItem DisplayName types. /// diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs index 023bd8ed33..112e2361de 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowWalker/Helpers/VirtualDesktopHelper.cs @@ -6,6 +6,7 @@ using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using System.Text; using Microsoft.CmdPal.Ext.WindowWalker.Properties; @@ -48,6 +49,10 @@ public class VirtualDesktopHelper /// private readonly List _availableDesktops = []; +#pragma warning disable SA1306 // Field names should begin with lower-case letter + private readonly uint CLSCTXINPROCALL = 0x17; +#pragma warning restore SA1306 // Field names should begin with lower-case letter + /// /// Id of the current visible Desktop. /// @@ -55,15 +60,27 @@ public class VirtualDesktopHelper private static readonly CompositeFormat VirtualDesktopHelperDesktop = System.Text.CompositeFormat.Parse(Properties.Resources.VirtualDesktopHelper_Desktop); + private Guid iVirtualDesktopManagerCLSID = new("aa509086-5ca9-4c25-8f95-589d3c07b48a"); + + private Guid iVirtualDesktopManagerIID = new("a5cd92ff-29be-454c-8d04-d82879fb3f1b"); + /// /// Initializes a new instance of the class. /// /// Setting to configure if the list of available desktops should update automatically or only when calling . Per default this is set to manual update (false) to have less registry queries. public VirtualDesktopHelper(bool desktopListUpdate = false) { + var cw = new StrategyBasedComWrappers(); + try { - _virtualDesktopManager = (IVirtualDesktopManager)new CVirtualDesktopManager(); + var hr = NativeMethods.CoCreateInstance(ref this.iVirtualDesktopManagerCLSID, nint.Zero, CLSCTXINPROCALL, ref iVirtualDesktopManagerIID, out var virtualDesktopManagerPtr); + if (hr != 0) + { + throw new ArgumentException($"Failed to create IVirtualDesktopManager instance. HR: 0x{hr:X}"); + } + + _virtualDesktopManager = (IVirtualDesktopManager)cw.GetOrCreateObjectForComInstance(virtualDesktopManagerPtr, CreateObjectFlags.None); } catch (COMException ex) { @@ -409,7 +426,7 @@ public class VirtualDesktopHelper /// Handle of the top level window. /// Guid of the target desktop. /// on success and on failure. - public bool MoveWindowToDesktop(IntPtr hWindow, in Guid desktopId) + public bool MoveWindowToDesktop(IntPtr hWindow, ref Guid desktopId) { if (_virtualDesktopManager == null) { @@ -417,7 +434,7 @@ public class VirtualDesktopHelper return false; } - var hr = _virtualDesktopManager.MoveWindowToDesktop(hWindow, desktopId); + var hr = _virtualDesktopManager.MoveWindowToDesktop(hWindow, ref desktopId); if (hr != (int)HRESULT.S_OK) { ExtensionHost.LogMessage(new LogMessage() { Message = "VirtualDesktopHelper.MoveWindowToDesktop() failed: An exception was thrown when moving the window ({hWindow}) to another desktop ({desktopId})." }); @@ -455,7 +472,7 @@ public class VirtualDesktopHelper } Guid newDesktop = _availableDesktops[windowDesktopNumber - 1]; - return MoveWindowToDesktop(hWindow, newDesktop); + return MoveWindowToDesktop(hWindow, ref newDesktop); } /// @@ -486,7 +503,7 @@ public class VirtualDesktopHelper } Guid newDesktop = _availableDesktops[windowDesktopNumber + 1]; - return MoveWindowToDesktop(hWindow, newDesktop); + return MoveWindowToDesktop(hWindow, ref newDesktop); } /// diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs index 39155115ca..4a5170250a 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileAsAdminCommand.cs @@ -3,18 +3,12 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Resources; -using System.Text; -using System.Threading.Tasks; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using ManagedCommon; using Microsoft.CmdPal.Ext.WindowsTerminal.Helpers; using Microsoft.CmdPal.Ext.WindowsTerminal.Properties; -using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; -using Windows.UI; namespace Microsoft.CmdPal.Ext.WindowsTerminal.Commands; @@ -68,7 +62,23 @@ internal sealed partial class LaunchProfileAsAdminCommand : InvokableCommand private void Launch(string id, string profile) { - var appManager = new ApplicationActivationManager(); + ComWrappers cw = new StrategyBasedComWrappers(); + + var hr = NativeHelpers.CoCreateInstance(ref NativeHelpers.ApplicationActivationManagerCLSID, IntPtr.Zero, NativeHelpers.CLSCTXINPROCALL, ref NativeHelpers.ApplicationActivationManagerIID, out var appManagerPtr); + + if (hr != 0) + { + throw new ArgumentException($"Failed to create IApplicationActivationManager instance. HR: 0x{hr:X}"); + } + + var appManager = (IApplicationActivationManager)cw.GetOrCreateObjectForComInstance( + appManagerPtr, CreateObjectFlags.None); + + if (appManager == null) + { + throw new ArgumentException("Failed to get IApplicationActivationManager interface"); + } + const ActivateOptions noFlags = ActivateOptions.None; var queryArguments = TerminalHelper.GetArguments(profile, _openNewTab, _openQuake); try diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs index a879dc2410..5f9d4ea00d 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Commands/LaunchProfileCommand.cs @@ -3,18 +3,12 @@ // See the LICENSE file in the project root for more information. using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Resources; -using System.Text; -using System.Threading.Tasks; +using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; using ManagedCommon; using Microsoft.CmdPal.Ext.WindowsTerminal.Helpers; using Microsoft.CmdPal.Ext.WindowsTerminal.Properties; -using Microsoft.CommandPalette.Extensions; using Microsoft.CommandPalette.Extensions.Toolkit; -using Windows.UI; namespace Microsoft.CmdPal.Ext.WindowsTerminal.Commands; @@ -38,7 +32,22 @@ internal sealed partial class LaunchProfileCommand : InvokableCommand private void Launch(string id, string profile) { - var appManager = new ApplicationActivationManager(); + ComWrappers cw = new StrategyBasedComWrappers(); + + var hr = NativeHelpers.CoCreateInstance(ref NativeHelpers.ApplicationActivationManagerCLSID, IntPtr.Zero, NativeHelpers.CLSCTXINPROCALL, ref NativeHelpers.ApplicationActivationManagerIID, out var appManagerPtr); + if (hr != 0) + { + throw new ArgumentException($"Failed to create IApplicationActivationManager instance. HR: 0x{hr:X}"); + } + + var appManager = (IApplicationActivationManager)cw.GetOrCreateObjectForComInstance( + appManagerPtr, CreateObjectFlags.None); + + if (appManager == null) + { + throw new ArgumentException("Failed to get IApplicationActivationManager interface"); + } + const ActivateOptions noFlags = ActivateOptions.None; var queryArguments = TerminalHelper.GetArguments(profile, _openNewTab, _openQuake); try diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs deleted file mode 100644 index a074d9c86d..0000000000 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/ApplicationActivationManager.cs +++ /dev/null @@ -1,24 +0,0 @@ -// Copyright (c) Microsoft Corporation -// The Microsoft Corporation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -namespace Microsoft.CmdPal.Ext.WindowsTerminal.Helpers; - -// Application Activation Manager Class -[ComImport] -[Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C")] -public class ApplicationActivationManager : IApplicationActivationManager -{ - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)/*, PreserveSig*/] - public extern IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId); - - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public extern IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId); - - [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)] - public extern IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId); -} diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs index e332eee6fd..c023323d7f 100644 --- a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/IApplicationActivationManager.cs @@ -4,6 +4,7 @@ using System; using System.Runtime.InteropServices; +using System.Runtime.InteropServices.Marshalling; namespace Microsoft.CmdPal.Ext.WindowsTerminal.Helpers; @@ -18,14 +19,13 @@ public enum ActivateOptions } // ApplicationActivationManager -[ComImport] +[GeneratedComInterface(StringMarshalling = StringMarshalling.Utf16)] [Guid("2e941141-7f97-4756-ba1d-9decde894a3d")] -[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] -public interface IApplicationActivationManager +public partial interface IApplicationActivationManager { - IntPtr ActivateApplication([In] string appUserModelId, [In] string arguments, [In] ActivateOptions options, [Out] out uint processId); + void ActivateApplication(string appUserModelId, string arguments, ActivateOptions options, out uint processId); - IntPtr ActivateForFile([In] string appUserModelId, [In] IntPtr /*IShellItemArray* */ itemArray, [In] string verb, [Out] out uint processId); + void ActivateForFile(string appUserModelId, IntPtr /*IShellItemArray* */ itemArray, string verb, out uint processId); - IntPtr ActivateForProtocol([In] string appUserModelId, [In] IntPtr /* IShellItemArray* */itemArray, [Out] out uint processId); + void ActivateForProtocol(string appUserModelId, IntPtr /* IShellItemArray* */itemArray, out uint processId); } diff --git a/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/NativeHelpers.cs b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/NativeHelpers.cs new file mode 100644 index 0000000000..e431d15a1b --- /dev/null +++ b/src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.WindowsTerminal/Helpers/NativeHelpers.cs @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation +// The Microsoft Corporation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.CmdPal.Ext.WindowsTerminal.Helpers; + +public sealed partial class NativeHelpers +{ + public const uint CLSCTXINPROCALL = 0x17; + + [LibraryImport("ole32.dll")] + public static partial uint CoCreateInstance( + ref Guid rclsid, + IntPtr pUnkOuter, + uint dwClsContext, + ref Guid riid, + out IntPtr rReturnedComObject); + +#pragma warning disable CA2211 // Non-constant fields should not be visible +#pragma warning disable SA1401 // Fields should be private + public static Guid ApplicationActivationManagerCLSID = new Guid("45BA127D-10A8-46EA-8AB7-56EA9078943C"); + public static Guid ApplicationActivationManagerIID = new Guid("2e941141-7f97-4756-ba1d-9decde894a3d"); +#pragma warning restore SA1401 // Fields should be private +#pragma warning restore CA2211 // Non-constant fields should not be visible +}