private static async Task parseFileOperation(AppServiceRequestReceivedEventArgs args) { var fileOp = (string)args.Request.Message["fileop"]; switch (fileOp) { case "Clipboard": await Win32API.StartSTATask(() => { System.Windows.Forms.Clipboard.Clear(); var fileToCopy = (string)args.Request.Message["filepath"]; var operation = (DataPackageOperation)(int)args.Request.Message["operation"]; var fileList = new System.Collections.Specialized.StringCollection(); fileList.AddRange(fileToCopy.Split('|')); if (operation == DataPackageOperation.Copy) { System.Windows.Forms.Clipboard.SetFileDropList(fileList); } else if (operation == DataPackageOperation.Move) { byte[] moveEffect = new byte[] { 2, 0, 0, 0 }; MemoryStream dropEffect = new MemoryStream(); dropEffect.Write(moveEffect, 0, moveEffect.Length); var data = new System.Windows.Forms.DataObject(); data.SetFileDropList(fileList); data.SetData("Preferred DropEffect", dropEffect); System.Windows.Forms.Clipboard.SetDataObject(data, true); } return(true); }); break; case "MoveToBin": var fileToDeletePath = (string)args.Request.Message["filepath"]; using (var op = new ShellFileOperations()) { op.Options = ShellFileOperations.OperationFlags.AllowUndo | ShellFileOperations.OperationFlags.NoUI; using var shi = new ShellItem(fileToDeletePath); op.QueueDeleteOperation(shi); op.PerformOperations(); } //ShellFileOperations.Delete(fileToDeletePath, ShellFileOperations.OperationFlags.AllowUndo | ShellFileOperations.OperationFlags.NoUI); break; case "ParseLink": var linkPath = (string)args.Request.Message["filepath"]; try { if (linkPath.EndsWith(".lnk")) { using var link = new ShellLink(linkPath, LinkResolution.NoUIWithMsgPump, null, TimeSpan.FromMilliseconds(100)); await args.Request.SendResponseAsync(new ValueSet() { { "TargetPath", link.TargetPath }, { "Arguments", link.Arguments }, { "WorkingDirectory", link.WorkingDirectory }, { "RunAsAdmin", link.RunAsAdministrator }, { "IsFolder", !string.IsNullOrEmpty(link.TargetPath) && link.Target.IsFolder } }); } else if (linkPath.EndsWith(".url")) { var linkUrl = await Win32API.StartSTATask(() => { var ipf = new Url.IUniformResourceLocator(); (ipf as System.Runtime.InteropServices.ComTypes.IPersistFile).Load(linkPath, 0); ipf.GetUrl(out var retVal); return(retVal); }); await args.Request.SendResponseAsync(new ValueSet() { { "TargetPath", linkUrl }, { "Arguments", null }, { "WorkingDirectory", null }, { "RunAsAdmin", false }, { "IsFolder", false } }); } } catch (Exception ex) { // Could not parse shortcut Logger.Warn(ex, ex.Message); await args.Request.SendResponseAsync(new ValueSet() { { "TargetPath", null }, { "Arguments", null }, { "WorkingDirectory", null }, { "RunAsAdmin", false }, { "IsFolder", false } }); } break; case "CreateLink": case "UpdateLink": var linkSavePath = (string)args.Request.Message["filepath"]; var targetPath = (string)args.Request.Message["targetpath"]; if (linkSavePath.EndsWith(".lnk")) { var arguments = (string)args.Request.Message["arguments"]; var workingDirectory = (string)args.Request.Message["workingdir"]; var runAsAdmin = (bool)args.Request.Message["runasadmin"]; using var newLink = new ShellLink(targetPath, arguments, workingDirectory); newLink.RunAsAdministrator = runAsAdmin; newLink.SaveAs(linkSavePath); // Overwrite if exists } else if (linkSavePath.EndsWith(".url")) { await Win32API.StartSTATask(() => { var ipf = new Url.IUniformResourceLocator(); ipf.SetUrl(targetPath, Url.IURL_SETURL_FLAGS.IURL_SETURL_FL_GUESS_PROTOCOL); (ipf as System.Runtime.InteropServices.ComTypes.IPersistFile).Save(linkSavePath, false); // Overwrite if exists return(true); }); } break; } }
private static async Task ParseArgumentsAsync(AppServiceRequestReceivedEventArgs args, AppServiceDeferral messageDeferral, string arguments, ApplicationDataContainer localSettings) { switch (arguments) { case "Terminate": // Exit fulltrust process (UWP is closed or suspended) appServiceExit.Set(); messageDeferral.Complete(); break; case "RecycleBin": var binAction = (string)args.Request.Message["action"]; await ParseRecycleBinActionAsync(args, binAction); break; case "DetectQuickLook": // Check QuickLook Availability var available = QuickLook.CheckQuickLookAvailability(); await args.Request.SendResponseAsync(new ValueSet() { { "IsAvailable", available } }); break; case "ToggleQuickLook": var path = (string)args.Request.Message["path"]; QuickLook.ToggleQuickLook(path); break; case "LoadContextMenu": var contextMenuResponse = new ValueSet(); var loadThreadWithMessageQueue = new Win32API.ThreadWithMessageQueue <ValueSet>(HandleMenuMessage); var cMenuLoad = await loadThreadWithMessageQueue.PostMessageAsync <Win32API.ContextMenu>(args.Request.Message); contextMenuResponse.Add("Handle", handleTable.AddValue(loadThreadWithMessageQueue)); contextMenuResponse.Add("ContextMenu", JsonConvert.SerializeObject(cMenuLoad)); await args.Request.SendResponseAsync(contextMenuResponse); break; case "ExecAndCloseContextMenu": var menuKey = (string)args.Request.Message["Handle"]; var execThreadWithMessageQueue = handleTable.GetValue <Win32API.ThreadWithMessageQueue <ValueSet> >(menuKey); if (execThreadWithMessageQueue != null) { await execThreadWithMessageQueue.PostMessage(args.Request.Message); } // The following line is needed to cleanup resources when menu is closed. // Unfortunately if you uncomment it some menu items will randomly stop working. // Resource cleanup is currently done on app closing, // if we find a solution for the issue above, we should cleanup as soon as a menu is closed. //handleTable.RemoveValue(menuKey); break; case "InvokeVerb": var filePath = (string)args.Request.Message["FilePath"]; var split = filePath.Split('|').Where(x => !string.IsNullOrWhiteSpace(x)); using (var cMenu = Win32API.ContextMenu.GetContextMenuForFiles(split.ToArray(), Shell32.CMF.CMF_DEFAULTONLY)) { cMenu?.InvokeVerb((string)args.Request.Message["Verb"]); } break; case "Bitlocker": var bitlockerAction = (string)args.Request.Message["action"]; if (bitlockerAction == "Unlock") { var drive = (string)args.Request.Message["drive"]; var password = (string)args.Request.Message["password"]; Win32API.UnlockBitlockerDrive(drive, password); await args.Request.SendResponseAsync(new ValueSet() { { "Bitlocker", "Unlock" } }); } break; case "SetVolumeLabel": var driveName = (string)args.Request.Message["drivename"]; var newLabel = (string)args.Request.Message["newlabel"]; Win32API.SetVolumeLabel(driveName, newLabel); break; case "FileOperation": await ParseFileOperationAsync(args); break; case "GetIconOverlay": var fileIconPath = (string)args.Request.Message["filePath"]; var thumbnailSize = (int)args.Request.Message["thumbnailSize"]; var iconOverlay = await Win32API.StartSTATask(() => Win32API.GetFileIconAndOverlay(fileIconPath, thumbnailSize)); await args.Request.SendResponseAsync(new ValueSet() { { "Icon", iconOverlay.icon }, { "Overlay", iconOverlay.overlay }, { "HasCustomIcon", iconOverlay.isCustom } }); break; case "NetworkDriveOperation": await ParseNetworkDriveOperationAsync(args); break; case "GetOneDriveAccounts": try { var oneDriveAccountsKey = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\OneDrive\Accounts", false); if (oneDriveAccountsKey == null) { await args.Request.SendResponseAsync(new ValueSet()); return; } var oneDriveAccounts = new ValueSet(); foreach (var account in oneDriveAccountsKey.GetSubKeyNames()) { var accountKeyName = @$ "{oneDriveAccountsKey.Name}\{account}"; var displayName = (string)Registry.GetValue(accountKeyName, "DisplayName", null); var userFolder = (string)Registry.GetValue(accountKeyName, "UserFolder", null); var accountName = string.IsNullOrWhiteSpace(displayName) ? "OneDrive" : $"OneDrive - {displayName}"; if (!string.IsNullOrWhiteSpace(userFolder) && !oneDriveAccounts.ContainsKey(accountName)) { oneDriveAccounts.Add(accountName, userFolder); } } await args.Request.SendResponseAsync(oneDriveAccounts); }