IEngineGetMenuCommandAsync Method |
Namespace: ITHit.FileSystem
Task<IMenuCommand> GetMenuCommandAsync( Guid menuGuid, IOperationContext operationContext = null )
To show context menu in Windows Explorer for your virtual drive follow these steps:
The code below is part of 'VirtualDrive' C# sample provided with the SDK.
<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" Executable="dummy.exe"> <com:Class Id="05CF065E-E135-4B2B-9D4D-CFB3FBAC73A4" /> </com:ExeServer> <com:ExeServer DisplayName="VirtualDrive" Executable="dummy.exe"> <com:Class Id="9C923BF3-3A4B-487B-AB4E-B4CF87FD1C25" /> </com:ExeServer> <com:ExeServer DisplayName="VirtualDrive" Executable="dummy.exe"> <com:Class Id="000562AA-2879-4CF1-89E8-0AEC9596FE19" /> </com:ExeServer> <com:ExeServer DisplayName="VirtualDrive" Executable="dummy.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.
public class MenuCommandLock : IMenuCommandWindows { private readonly VirtualEngineBase engine; private readonly ILogger logger; private const string lockCommandIcon = @"Images\Locked.ico"; private const string unlockCommandIcon = @"Images\Unlocked.ico"; public MenuCommandLock(VirtualEngineBase 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) { // This sample can not lock folders. // Hide menu if any folders are selected. foreach (string userFileSystemPath in filesPath) { FileAttributes attr = File.GetAttributes(userFileSystemPath); if ((attr & FileAttributes.Directory) == FileAttributes.Directory) return MenuState.Hidden; } bool? isLocked = await IsLockedAsync(filesPath); return isLocked.HasValue ? MenuState.Enabled : MenuState.Hidden; } public async Task InvokeAsync(IEnumerable<string> filesPath, IEnumerable<byte[]> remoteStorageItemIds = null, CancellationToken cancellationToken = default) { // 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 { bool isLocked = false; if (engine.Placeholders.TryGetItem(userFileSystemPath, out PlaceholderItem placeholder)) { if (placeholder.Properties.TryGetLockInfo(out ServerLockInfo lockInfo)) { // Detect if locked by this user. if (!engine.IsCurrentUser(lockInfo.Owner)) { // Typically we can not unlock items locked by other users. // We must hide or disable menu in this case. return null; } isLocked = true; } } 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.
public override async Task<IMenuCommand> GetMenuCommandAsync(Guid menuGuid, IOperationContext operationContext = null) { // 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(), default, operationContext); Guid menuCommandLockGuid = typeof(ShellExtension.ContextMenuVerbIntegrated).GUID; if (menuGuid == menuCommandLockGuid) { return new MenuCommandLock(this, this.Logger); } Logger.LogError($"Menu not found", Path, menuGuid.ToString(), default, operationContext); throw new NotImplementedException(); }