diff --git a/src/CommandEnumerator.cs b/src/CommandEnumerator.cs
index c6ab234..d6635e8 100644
--- a/src/CommandEnumerator.cs
+++ b/src/CommandEnumerator.cs
@@ -1,37 +1,41 @@
-using Juknum.Windows.ContextMenu.Interfaces;
-using System.Runtime.InteropServices;
-using Vanara.PInvoke;
-
-namespace Juknum.Windows.ContextMenu;
-
-[ComVisible(false)]
-internal class CommandEnumerator(IExplorerCommand[] commands) : IEnumExplorerCommand {
- private int index = 0;
- private readonly IExplorerCommand[] commands = commands;
-
- #region IEnumExplorerCommand Members
- public HRESULT Next(uint celt, IExplorerCommand[] pUICommand, IntPtr pceltFetched) {
- uint fetched = 0;
-
- while (fetched < celt && index < commands.Length) {
- pUICommand[fetched++] = commands[index++];
- }
-
- return fetched == celt ? HRESULT.S_OK : HRESULT.S_FALSE;
- }
-
- public HRESULT Skip(uint celt) {
- index += (int)celt;
-
- if (index > commands.Length) {
- index = commands.Length;
- return HRESULT.S_FALSE;
- }
-
- return HRESULT.S_OK;
- }
-
- public void Reset() => index = 0;
- public IEnumExplorerCommand Clone() => new CommandEnumerator(commands) { index = this.index };
- #endregion
-}
+using System.Runtime.InteropServices;
+using Vanara.PInvoke;
+using static Vanara.PInvoke.Shell32;
+
+namespace Juknum.Windows.ContextMenu;
+
+[ComVisible(false)]
+internal class CommandEnumerator(IExplorerCommand[] commands) : IEnumExplorerCommand {
+ private int index = 0;
+ private readonly IExplorerCommand[] commands = commands;
+
+ #region IEnumExplorerCommand Members
+ public HRESULT Next(uint celt, IExplorerCommand[] pUICommand, IntPtr pceltFetched) {
+ uint fetched = 0;
+
+ while (fetched < celt && index < commands.Length) {
+ pUICommand[fetched++] = commands[index++];
+ }
+
+ if (pceltFetched != IntPtr.Zero) {
+ Marshal.WriteInt32(pceltFetched, (int)fetched);
+ }
+
+ return fetched == celt ? HRESULT.S_OK : HRESULT.S_FALSE;
+ }
+
+ public HRESULT Skip(uint celt) {
+ index += (int)celt;
+
+ if (index > commands.Length) {
+ index = commands.Length;
+ return HRESULT.S_FALSE;
+ }
+
+ return HRESULT.S_OK;
+ }
+
+ public void Reset() => index = 0;
+ public IEnumExplorerCommand Clone() => new CommandEnumerator(commands) { index = this.index };
+ #endregion
+}
diff --git a/src/ExplorerCommand.cs b/src/ExplorerCommand.cs
index 8dec643..c97998d 100644
--- a/src/ExplorerCommand.cs
+++ b/src/ExplorerCommand.cs
@@ -1,94 +1,94 @@
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using Vanara.PInvoke;
-using static Vanara.PInvoke.Shell32;
-
-namespace Juknum.Windows.ContextMenu;
-
-[ComVisible(false)]
-public abstract class ExplorerCommand : Interfaces.IExplorerCommand {
-
- ///
- /// Unique identifier (GUID) of the command.
- ///
- public abstract Guid Guid { get; }
-
- ///
- /// Title of the command, which is displayed in the context menu.
- ///
- public abstract string Title { get; }
-
- ///
- /// Optional icon for the command, which is displayed in the context menu.
- ///
- public virtual string? Icon { get; } = null;
-
- ///
- /// Optional tooltip for the command, which is displayed when hovering over the command in the context menu.
- /// Note: This property is not used by Windows Explorer.
- ///
- public virtual string? ToolTip { get; } = null;
-
- ///
- /// Determines whether the command is enabled for the given shell item array.
- ///
- /// The shell item array for which to determine command enablement.
- /// Indicates whether the operation can be slow.
- /// true if the command is enabled; otherwise, false.
- public virtual bool IsEnabled(IShellItemArray psiItemArray, bool canBeSlow) => true;
-
- ///
- /// The method that is called when the command is executed.
- /// This method should be overridden to provide custom behavior for the command.
- ///
- /// The shell item array for which to execute the command.
- /// The bind context for the command.
- /// true if the command was executed successfully; otherwise, false.
- public abstract bool Execute(IShellItemArray psiItemArray, IBindCtx? pbc);
-
- #region IExplorerCommand Members
- public HRESULT GetTitle(IShellItemArray psiItemArray, out string? ppszName) {
- ppszName = Title;
- return HRESULT.S_OK;
- }
-
- public HRESULT GetIcon(IShellItemArray psiItemArray, out string? ppszIcon) {
- ppszIcon = Icon;
- return Icon is null ? HRESULT.E_NOTIMPL : HRESULT.S_OK;
- }
-
- public HRESULT GetToolTip(IShellItemArray psiItemArray, out string? ppszInfotip) {
- ppszInfotip = ToolTip;
- return ToolTip is null ? HRESULT.E_NOTIMPL : HRESULT.S_OK;
- }
-
- public HRESULT GetCanonicalName(out Guid pguidCommandName) {
- pguidCommandName = Guid;
- return HRESULT.S_OK;
- }
-
- public HRESULT GetState(IShellItemArray psiItemArray, bool fOkToBeSlow, out EXPCMDSTATE pCmdState) {
- pCmdState = IsEnabled(psiItemArray, fOkToBeSlow) ? EXPCMDSTATE.ECS_ENABLED : EXPCMDSTATE.ECS_DISABLED;
- return HRESULT.S_OK;
- }
-
- public virtual HRESULT Invoke(IShellItemArray psiItemArray, IBindCtx? pbc) {
- try {
- return Execute(psiItemArray, pbc) ? HRESULT.S_OK : HRESULT.S_FALSE;
- }
- catch {
- return HRESULT.E_FAIL;
- }
- }
-
- public virtual HRESULT GetFlags(out EXPCMDFLAGS pFlags) {
- pFlags = EXPCMDFLAGS.ECF_DEFAULT;
- return HRESULT.S_OK;
- }
-
- public virtual HRESULT EnumSubCommands(out Interfaces.IEnumExplorerCommand? ppEnum) {
- ppEnum = null;
- return HRESULT.E_NOTIMPL;
- }
- #endregion
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using Vanara.PInvoke;
+using static Vanara.PInvoke.Shell32;
+
+namespace Juknum.Windows.ContextMenu;
+
+[ComVisible(false)]
+public abstract class ExplorerCommand : IExplorerCommand {
+
+ ///
+ /// Unique identifier (GUID) of the command.
+ ///
+ public abstract Guid Guid { get; }
+
+ ///
+ /// Title of the command, which is displayed in the context menu.
+ ///
+ public abstract string Title { get; }
+
+ ///
+ /// Optional icon for the command, which is displayed in the context menu.
+ ///
+ public virtual string? Icon { get; } = null;
+
+ ///
+ /// Optional tooltip for the command, which is displayed when hovering over the command in the context menu.
+ /// Note: This property is not used by Windows Explorer.
+ ///
+ public virtual string? ToolTip { get; } = null;
+
+ ///
+ /// Determines whether the command is enabled for the given shell item array.
+ ///
+ /// The shell item array for which to determine command enablement.
+ /// Indicates whether the operation can be slow.
+ /// true if the command is enabled; otherwise, false.
+ public virtual bool IsEnabled(IShellItemArray psiItemArray, bool canBeSlow) => true;
+
+ ///
+ /// The method that is called when the command is executed.
+ /// This method should be overridden to provide custom behavior for the command.
+ ///
+ /// The shell item array for which to execute the command.
+ /// The bind context for the command.
+ /// true if the command was executed successfully; otherwise, false.
+ public abstract bool Execute(IShellItemArray psiItemArray, IBindCtx? pbc);
+
+ #region IExplorerCommand Members
+ public HRESULT GetTitle(IShellItemArray psiItemArray, out string? ppszName) {
+ ppszName = Title;
+ return HRESULT.S_OK;
+ }
+
+ public HRESULT GetIcon(IShellItemArray psiItemArray, out string? ppszIcon) {
+ ppszIcon = Icon;
+ return Icon is null ? HRESULT.E_NOTIMPL : HRESULT.S_OK;
+ }
+
+ public HRESULT GetToolTip(IShellItemArray psiItemArray, out string? ppszInfotip) {
+ ppszInfotip = ToolTip;
+ return ToolTip is null ? HRESULT.E_NOTIMPL : HRESULT.S_OK;
+ }
+
+ public HRESULT GetCanonicalName(out Guid pguidCommandName) {
+ pguidCommandName = Guid;
+ return HRESULT.S_OK;
+ }
+
+ public HRESULT GetState(IShellItemArray psiItemArray, bool fOkToBeSlow, out EXPCMDSTATE pCmdState) {
+ pCmdState = IsEnabled(psiItemArray, fOkToBeSlow) ? EXPCMDSTATE.ECS_ENABLED : EXPCMDSTATE.ECS_DISABLED;
+ return HRESULT.S_OK;
+ }
+
+ public virtual HRESULT Invoke(IShellItemArray psiItemArray, IBindCtx? pbc) {
+ try {
+ return Execute(psiItemArray, pbc) ? HRESULT.S_OK : HRESULT.S_FALSE;
+ }
+ catch {
+ return HRESULT.E_FAIL;
+ }
+ }
+
+ public virtual HRESULT GetFlags(out EXPCMDFLAGS pFlags) {
+ pFlags = EXPCMDFLAGS.ECF_DEFAULT;
+ return HRESULT.S_OK;
+ }
+
+ public virtual HRESULT EnumSubCommands(out IEnumExplorerCommand? ppEnum) {
+ ppEnum = null;
+ return HRESULT.E_NOTIMPL;
+ }
+ #endregion
}
\ No newline at end of file
diff --git a/src/ExplorerCommandMenu.cs b/src/ExplorerCommandMenu.cs
index 2bca94f..cf20876 100644
--- a/src/ExplorerCommandMenu.cs
+++ b/src/ExplorerCommandMenu.cs
@@ -1,48 +1,48 @@
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using Vanara.PInvoke;
-using static Vanara.PInvoke.Shell32;
-
-namespace Juknum.Windows.ContextMenu;
-
-[ComVisible(false)]
-public abstract class ExplorerCommandMenu : ExplorerCommand {
- ///
- /// Array of objects that represent the commands in the menu.
- ///
- public abstract ExplorerCommand[] Commands { get; }
-
- #region ExplorerCommand Members
- ///
- /// Does not execute any command when the menu is clicked.
- /// Override this method to provide custom behavior for the menu.
- ///
- /// The shell item array for which to execute the command.
- /// The bind context for the command.
- /// true if the command was executed successfully; otherwise, false.
- public override bool Execute(IShellItemArray psiItemArray, IBindCtx? pbc) => true;
- #endregion
-
- #region IExplorerCommand Members
- public override HRESULT Invoke(IShellItemArray psiItemArray, IBindCtx? pbc) {
- // Do nothing when the menu is clicked. The menu will be displayed automatically by Windows Explorer.
- return HRESULT.E_NOTIMPL;
- }
-
- public override HRESULT GetFlags(out EXPCMDFLAGS pFlags) {
- pFlags = EXPCMDFLAGS.ECF_HASSUBCOMMANDS;
- return HRESULT.S_OK;
- }
-
- public override HRESULT EnumSubCommands(out Interfaces.IEnumExplorerCommand? ppEnum) {
- try {
- ppEnum = new CommandEnumerator(Commands);
- return HRESULT.S_OK;
- }
- catch {
- ppEnum = null;
- return HRESULT.S_FALSE;
- }
- }
- #endregion
-}
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using Vanara.PInvoke;
+using static Vanara.PInvoke.Shell32;
+
+namespace Juknum.Windows.ContextMenu;
+
+[ComVisible(false)]
+public abstract class ExplorerCommandMenu : ExplorerCommand {
+ ///
+ /// Array of objects that represent the commands in the menu.
+ ///
+ public abstract ExplorerCommand[] Commands { get; }
+
+ #region ExplorerCommand Members
+ ///
+ /// Does not execute any command when the menu is clicked.
+ /// Override this method to provide custom behavior for the menu.
+ ///
+ /// The shell item array for which to execute the command.
+ /// The bind context for the command.
+ /// true if the command was executed successfully; otherwise, false.
+ public override bool Execute(IShellItemArray psiItemArray, IBindCtx? pbc) => true;
+ #endregion
+
+ #region IExplorerCommand Members
+ public override HRESULT Invoke(IShellItemArray psiItemArray, IBindCtx? pbc) {
+ // Do nothing when the menu is clicked. The menu will be displayed automatically by Windows Explorer.
+ return HRESULT.E_NOTIMPL;
+ }
+
+ public override HRESULT GetFlags(out EXPCMDFLAGS pFlags) {
+ pFlags = EXPCMDFLAGS.ECF_HASSUBCOMMANDS;
+ return HRESULT.S_OK;
+ }
+
+ public override HRESULT EnumSubCommands(out IEnumExplorerCommand? ppEnum) {
+ try {
+ ppEnum = new CommandEnumerator(Commands);
+ return HRESULT.S_OK;
+ }
+ catch {
+ ppEnum = null;
+ return HRESULT.S_FALSE;
+ }
+ }
+ #endregion
+}
diff --git a/src/Interfaces/IEnumExplorerCommand.cs b/src/Interfaces/IEnumExplorerCommand.cs
deleted file mode 100644
index 9224301..0000000
--- a/src/Interfaces/IEnumExplorerCommand.cs
+++ /dev/null
@@ -1,29 +0,0 @@
-
-using System.Runtime.InteropServices;
-using Vanara.PInvoke;
-
-namespace Juknum.Windows.ContextMenu.Interfaces;
-
-///
-// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ienumexplorercommand
-[PInvokeData("shobjidl_core.h", MSDNShortId = "c9a21e84-dd95-413a-b9db-e02008185bef")]
-[ComImport, Guid("a88826f8-186f-4987-aade-ea0cef8fbfe8"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
-public interface IEnumExplorerCommand : Vanara.Collections.ICOMEnum {
-
- // Here we switched the "out uint pceltFetched" parameter to IntPtr because the original method signature uses
- // a pointer to an unsigned integer, which is not directly compatible with C#'s out parameter.
- ///
- [PreserveSig]
- HRESULT Next([In] uint celt, [Out, MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface, SizeParamIndex = 0)] IExplorerCommand[] pUICommand, IntPtr pceltFetched);
-
- ///
- [PreserveSig]
- HRESULT Skip([In] uint celt);
-
- ///
- void Reset();
-
- ///
- [return: MarshalAs(UnmanagedType.Interface)]
- IEnumExplorerCommand Clone();
-}
diff --git a/src/Interfaces/IExplorerCommand.cs b/src/Interfaces/IExplorerCommand.cs
deleted file mode 100644
index c86f27f..0000000
--- a/src/Interfaces/IExplorerCommand.cs
+++ /dev/null
@@ -1,47 +0,0 @@
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using Vanara.PInvoke;
-using static Vanara.PInvoke.Shell32;
-
-namespace Juknum.Windows.ContextMenu.Interfaces;
-
-///
-// https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-iexplorercommand
-[PInvokeData("shobjidl_core.h", MSDNShortId = "61e94e50-9e12-4a2c-a6c7-64a9181f80b8")]
-[ComImport, Guid("a08ce4d0-fa25-44ab-b57c-c7b1c323e0b9"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
-public interface IExplorerCommand {
-
- ///
- [PreserveSig]
- HRESULT GetTitle(IShellItemArray psiItemArray, [MarshalAs(UnmanagedType.LPWStr)] out string? ppszName);
-
- ///
- [PreserveSig]
- HRESULT GetIcon(IShellItemArray psiItemArray, [MarshalAs(UnmanagedType.LPWStr)] out string? ppszIcon);
-
- ///
- [PreserveSig]
- HRESULT GetToolTip(IShellItemArray psiItemArray, [MarshalAs(UnmanagedType.LPWStr)] out string? ppszInfotip);
-
- ///
- [PreserveSig]
- HRESULT GetCanonicalName(out Guid pguidCommandName);
-
- ///
- [PreserveSig]
- HRESULT GetState(IShellItemArray psiItemArray, [MarshalAs(UnmanagedType.Bool)] bool fOkToBeSlow, out EXPCMDSTATE pCmdState);
-
- ///
- [PreserveSig]
- HRESULT Invoke(IShellItemArray psiItemArray, [Optional] IBindCtx? pbc);
-
- ///
- [PreserveSig]
- HRESULT GetFlags(out EXPCMDFLAGS pFlags);
-
- // We use our own IEnumExplorerCommand interface here to fix the Next() method
- // signature from Vanara.PInvoke.Shell32.IEnumExplorerCommand as it is bugged.
- ///
- [PreserveSig]
- HRESULT EnumSubCommands(out Interfaces.IEnumExplorerCommand? ppEnum);
-}
diff --git a/src/Juknum.Windows.ContextMenu.csproj b/src/Juknum.Windows.ContextMenu.csproj
index b948021..20e5a71 100644
--- a/src/Juknum.Windows.ContextMenu.csproj
+++ b/src/Juknum.Windows.ContextMenu.csproj
@@ -24,7 +24,7 @@
-
+