private static object HandleMenuMessage(ValueSet message, Win32API.DisposableDictionary table) { switch ((string)message["Arguments"]) { case "LoadContextMenu": var contextMenuResponse = new ValueSet(); var filePath = (string)message["FilePath"]; var extendedMenu = (bool)message["ExtendedMenu"]; var showOpenMenu = (bool)message["ShowOpenMenu"]; var split = filePath.Split('|').Where(x => !string.IsNullOrWhiteSpace(x)); var cMenuLoad = Win32API.ContextMenu.GetContextMenuForFiles(split.ToArray(), extendedMenu ? Shell32.CMF.CMF_EXTENDEDVERBS : Shell32.CMF.CMF_NORMAL, FilterMenuItems(showOpenMenu)); table.SetValue("MENU", cMenuLoad); return(cMenuLoad); case "ExecAndCloseContextMenu": var cMenuExec = table.GetValue <Win32API.ContextMenu>("MENU"); cMenuExec?.InvokeItem(message.Get("ItemID", -1)); // 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. //table.RemoveValue("MENU"); return(null); default: return(null); } }
private static void Main(string[] args) { StorageFolder storageFolder = ApplicationData.Current.LocalFolder; LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NLog.config")); LogManager.Configuration.Variables["LogPath"] = storageFolder.Path; AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; if (HandleCommandLineArgs()) { // Handles OpenShellCommandInExplorer return; } // Only one instance of the fulltrust process allowed // This happens if multiple instances of the UWP app are launched using var mutex = new Mutex(true, "FilesUwpFullTrust", out bool isNew); if (!isNew) { return; } try { // Create handle table to store e.g. context menu references handleTable = new Win32API.DisposableDictionary(); // Create shell COM object and get recycle bin folder recycler = new ShellFolder(Shell32.KNOWNFOLDERID.FOLDERID_RecycleBinFolder); ApplicationData.Current.LocalSettings.Values["RecycleBin_Title"] = recycler.Name; // Create filesystem watcher to monitor recycle bin folder(s) // SHChangeNotifyRegister only works if recycle bin is open in explorer :( watchers = new List <FileSystemWatcher>(); var sid = System.Security.Principal.WindowsIdentity.GetCurrent().User.ToString(); foreach (var drive in DriveInfo.GetDrives()) { var recycle_path = Path.Combine(drive.Name, "$Recycle.Bin", sid); if (!Directory.Exists(recycle_path)) { continue; } var watcher = new FileSystemWatcher(); watcher.Path = recycle_path; watcher.Filter = "*.*"; watcher.NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName; watcher.Created += Watcher_Changed; watcher.Deleted += Watcher_Changed; watcher.EnableRaisingEvents = true; watchers.Add(watcher); } // Preload context menu for better performace // We query the context menu for the app's local folder var preloadPath = ApplicationData.Current.LocalFolder.Path; using var _ = Win32API.ContextMenu.GetContextMenuForFiles(new string[] { preloadPath }, Shell32.CMF.CMF_NORMAL); // Connect to app service and wait until the connection gets closed appServiceExit = new AutoResetEvent(false); InitializeAppServiceConnection(); appServiceExit.WaitOne(); } finally { connection?.Dispose(); foreach (var watcher in watchers) { watcher.Dispose(); } handleTable?.Dispose(); recycler?.Dispose(); appServiceExit?.Dispose(); mutex?.ReleaseMutex(); } }
private static void Main(string[] args) { StorageFolder storageFolder = ApplicationData.Current.LocalFolder; LogManager.Configuration = new NLog.Config.XmlLoggingConfiguration(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "NLog.config")); LogManager.Configuration.Variables["LogPath"] = storageFolder.Path; AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionTrapper; if (HandleCommandLineArgs()) { // Handles OpenShellCommandInExplorer return; } try { // Create handle table to store e.g. context menu references handleTable = new Win32API.DisposableDictionary(); // Create shell COM object and get recycle bin folder using var recycler = new ShellFolder(Shell32.KNOWNFOLDERID.FOLDERID_RecycleBinFolder); ApplicationData.Current.LocalSettings.Values["RecycleBin_Title"] = recycler.Name; // Create filesystem watcher to monitor recycle bin folder(s) // SHChangeNotifyRegister only works if recycle bin is open in explorer :( binWatchers = new List <FileSystemWatcher>(); var sid = WindowsIdentity.GetCurrent().User.ToString(); foreach (var drive in DriveInfo.GetDrives()) { var recyclePath = Path.Combine(drive.Name, "$Recycle.Bin", sid); if (drive.DriveType == DriveType.Network || !Directory.Exists(recyclePath)) { continue; } var watcher = new FileSystemWatcher { Path = recyclePath, Filter = "*.*", NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.FileName | NotifyFilters.DirectoryName }; watcher.Created += Watcher_Changed; watcher.Deleted += Watcher_Changed; watcher.EnableRaisingEvents = true; binWatchers.Add(watcher); } // Preload context menu for better performance // We query the context menu for the app's local folder var preloadPath = ApplicationData.Current.LocalFolder.Path; using var _ = Win32API.ContextMenu.GetContextMenuForFiles(new string[] { preloadPath }, Shell32.CMF.CMF_NORMAL | Shell32.CMF.CMF_SYNCCASCADEMENU, FilterMenuItems(false)); // Create cancellation token for drop window cancellation = new CancellationTokenSource(); // Connect to app service and wait until the connection gets closed appServiceExit = new AutoResetEvent(false); InitializeAppServiceConnection(); // Initialize device watcher deviceWatcher = new DeviceWatcher(connection); deviceWatcher.Start(); // Wait until the connection gets closed appServiceExit.WaitOne(); } finally { connection?.Dispose(); foreach (var watcher in binWatchers) { watcher.Dispose(); } handleTable?.Dispose(); deviceWatcher?.Dispose(); cancellation?.Cancel(); cancellation?.Dispose(); appServiceExit?.Dispose(); } }