Click or drag to resize

IEngineGetMenuCommandAsync Method

IT Hit User File System
Gets context menu command.

Namespace:  ITHit.FileSystem
Assembly:  ITHit.FileSystem (in ITHit.FileSystem.dll) Version: 6.0.16872.0-Beta
Syntax
Task<IMenuCommand> GetMenuCommandAsync(
	Guid menuGuid
)

Parameters

menuGuid
Type: SystemGuid
Context menu command GUID.

Return Value

Type: TaskIMenuCommand
Menu implemntation.
Remarks

To show context menu in Windows Explorer for your virtual drive follow these steps:

  1. Derive your class from the [!:CloudFilesContextMenuVerbBase] class. Add the GuidAttribute, ProgIdAttribute and ComVisibleAttribute attributes to your class. You do not need to implement any methods in your class. On Windows 11 your module that contains menu class requires package or application identity (be signed with a trusted certificate).
  2. Add the desktop3:CloudFilesContextMenus tag to your Package.appxmanifest (in case of packaged app) or appxmanifest.xml (in case of a sparse package) that references your class.
  3. Implement the IMenuCommand interface to return the menu data.
  4. Return your object that implements IMenuCommand from the GetMenuCommandAsync(Guid) method.

Examples

The code below is part of 'VirtualDrive' C# sample provided with the SDK.

C#
[ComVisible(true)]
[ProgId("VirtualDrive.ContextMenuVerb")]
[Guid("9C923BF3-3A4B-487B-AB4E-B4CF87FD1C25")]
public class ContextMenuVerbRpc : CloudFilesContextMenuVerbRpcBase
{

}

The code below is part of 'VirtualDrive' C# sample provided with the SDK.

XML
<Extensions>
  <desktop3:Extension Category="windows.cloudFiles">
    <desktop3:CloudFiles>
      <desktop3:CustomStateHandler Clsid="000562AA-2879-4CF1-89E8-0AEC9596FE19"/>
      <desktop3:ThumbnailProviderHandler Clsid="05CF065E-E135-4B2B-9D4D-CFB3FBAC73A4"/>

      <desktop3:ExtendedPropertyHandler Clsid="20000000-0000-0000-0000-000000000001"/>
      <desktop3:BannersHandler Clsid="20000000-0000-0000-0000-000000000001"/>

      <desktop3:CloudFilesContextMenus>
        <desktop3:Verb Id="LockCommand" Clsid="9C923BF3-3A4B-487B-AB4E-B4CF87FD1C25" />
      </desktop3:CloudFilesContextMenus>

      <desktop4:ContentUriSource Clsid="6D45BC7A-D0B7-4913-8984-FD7261550C08"/>

    </desktop3:CloudFiles>
  </desktop3:Extension>
  <com:Extension Category="windows.comServer">
    <com:ComServer>
      <com:ExeServer DisplayName="VirtualDrive.ShellExtension" Executable="VirtualDrive.ShellExtension\VirtualDrive.ShellExtension.exe">
        <com:Class Id="05CF065E-E135-4B2B-9D4D-CFB3FBAC73A4" />
      </com:ExeServer>

      <com:ExeServer DisplayName="VirtualDrive.ShellExtension" Executable="VirtualDrive.ShellExtension\VirtualDrive.ShellExtension.exe">
        <com:Class Id="9C923BF3-3A4B-487B-AB4E-B4CF87FD1C25" />
      </com:ExeServer>

      <com:ExeServer DisplayName="VirtualDrive.ShellExtension" Executable="VirtualDrive.ShellExtension\VirtualDrive.ShellExtension.exe">
          <com:Class Id="000562AA-2879-4CF1-89E8-0AEC9596FE19" />
      </com:ExeServer>

        <com:ExeServer DisplayName="VirtualDrive.ShellExtension" Executable="VirtualDrive.ShellExtension\VirtualDrive.ShellExtension.exe">
          <com:Class Id="6D45BC7A-D0B7-4913-8984-FD7261550C08" />
      </com:ExeServer>

    </com:ComServer>
  </com:Extension>
</Extensions>

The code below is part of 'Common' C# sample provided with the SDK.

C#
public class MenuCommandLock : IMenuCommandWindows
{
    private readonly EngineWindows engine;
    private readonly ILogger logger;

    private const string lockCommandIcon = @"Images\Locked.ico";
    private const string unlockCommandIcon = @"Images\Unlocked.ico";

    public MenuCommandLock(EngineWindows engine, ILogger logger)
    {
        this.engine = engine;
        this.logger = logger.CreateLogger("Lock Menu Command");
    }

    public async Task<string> GetTitleAsync(IEnumerable<string> filesPath)
    {
        bool isLocked = await IsLockedAsync(filesPath) == true;
        return isLocked ? "Unlock" : "Lock";
    }

    public async Task<string> GetIconAsync(IEnumerable<string> filesPath)
    {
        string iconName = await IsLockedAsync(filesPath) == false ? lockCommandIcon : unlockCommandIcon;
        string iconPath = Path.Combine(Path.GetDirectoryName(typeof(MenuCommandLock).Assembly.Location), iconName);
        return iconPath;
    }

    public async Task<MenuState> GetStateAsync(IEnumerable<string> filesPath)
    {
        bool? isLocked = await IsLockedAsync(filesPath);
        return isLocked.HasValue ? MenuState.Enabled : MenuState.Hidden;
    }

    public async Task InvokeAsync(IEnumerable<string> filesPath)
    {
        // If you need a remote storage ID for each item use the following code:
        //foreach (string userFileSystemPath in filesPath)
        //{
        //    if(engine.Placeholders.TryGetItem(userFileSystemPath, out PlaceholderItem placeholder))
        //    {
        //        byte[] remoteStorageId = placeholder.GetRemoteStorageItemId();
        //    }
        //}

        bool isLocked = await IsLockedAsync(filesPath) == true;
        foreach (string userFileSystemPath in filesPath)
        {
            try
            {
                IClientNotifications clientNotifications = engine.ClientNotifications(userFileSystemPath, logger);
                if (isLocked)
                    await clientNotifications.UnlockAsync();
                else
                    await clientNotifications.LockAsync();
            }
            catch (Exception ex)
            {
                string actionName = isLocked ? "Unlock" : "Lock";
                logger.LogError($"Failed to {actionName} item", userFileSystemPath, null, ex);
            }
        }
    }

    public async Task<string> GetToolTipAsync(IEnumerable<string> filesPath)
    {
        bool isLocked = await IsLockedAsync(filesPath) == true;
        return isLocked ? "Unlock item(s)" : "Lock item(s)";
    }

    private async Task<bool?> IsLockedAsync(IEnumerable<string> filesPath, CancellationToken cancellationToken = default)
    {
        bool? allLocked = null;
        foreach (string userFileSystemPath in filesPath)
        {
            try
            {
                IClientNotifications clientNotifications = engine.ClientNotifications(userFileSystemPath, logger);
                LockMode lockMode = await clientNotifications.GetLockModeAsync(cancellationToken);

                bool isLocked = lockMode != LockMode.None;

                if(allLocked.HasValue && (allLocked != isLocked))
                {
                    return null;
                }

                allLocked = isLocked;
            }
            catch (Exception ex)
            {
                logger.LogError("Failed to get lock state", userFileSystemPath, null, ex);
            }
        }

        return allLocked;
    }
}

The code below is part of 'VirtualDrive' C# sample provided with the SDK.

C#
public override async Task<IMenuCommand> GetMenuCommandAsync(Guid menuGuid)
{
    // For this method to be called you need to register a menu command handler.
    // See method description for more details.

    Logger.LogDebug($"{nameof(IEngine)}.{nameof(GetMenuCommandAsync)}()", menuGuid.ToString());

    Guid menuCommandLockGuid = typeof(ShellExtension.ContextMenuVerbIntegrated).GUID;

    if (menuGuid == menuCommandLockGuid)
    {
        return new MenuCommandLock(this, this.Logger);
    }

    Logger.LogError($"Menu not found", menuGuid.ToString());
    throw new NotImplementedException();
}
See Also