private async Task HandleShellRecentItemsMessage(Dictionary <string, object> message) { var action = (string)message["action"]; var response = new ValueSet(); switch (action) { // enumerate `\Windows\Recent` for recent folders // note: files are enumerated using (Win32MessageHandler: "ShellFolder") in RecentItemsManager case "EnumerateFolders": var enumerateFoldersResponse = await Win32API.StartSTATask(() => { try { var shellLinkItems = new List <ShellLinkItem>(); var excludeMask = FileAttributes.Hidden; var linkFilePaths = Directory.EnumerateFiles(RecentItemsPath).Where(f => (new FileInfo(f).Attributes & excludeMask) == 0); foreach (var linkFilePath in linkFilePaths) { using var link = new ShellLink(linkFilePath, LinkResolution.NoUIWithMsgPump, null, TimeSpan.FromMilliseconds(100)); try { if (!string.IsNullOrEmpty(link.TargetPath) && link.Target.IsFolder) { var shellLinkItem = ShellFolderExtensions.GetShellLinkItem(link); shellLinkItems.Add(shellLinkItem); } } catch (FileNotFoundException) { // occurs when shortcut or shortcut target is deleted and accessed (link.Target) // consequently, we shouldn't include the item as a recent item } } response.Add("EnumerateFolders", JsonConvert.SerializeObject(shellLinkItems)); } catch (Exception e) { Program.Logger.Warn(e); } return(response); }); await Win32API.SendMessageAsync(connection, enumerateFoldersResponse, message.Get("RequestID", (string)null)); break; case "Add": var addResponse = await Win32API.StartSTATask(() => { try { var path = (string)message["Path"]; Shell32.SHAddToRecentDocs(Shell32.SHARD.SHARD_PATHW, path); } catch (Exception e) { Program.Logger.Warn(e); } return(response); }); await Win32API.SendMessageAsync(connection, addResponse, message.Get("RequestID", (string)null)); break; case "Clear": var clearResponse = await Win32API.StartSTATask(() => { try { Shell32.SHAddToRecentDocs(Shell32.SHARD.SHARD_PIDL, (string)null); } catch (Exception e) { Program.Logger.Warn(e); } return(response); }); await Win32API.SendMessageAsync(connection, clearResponse, message.Get("RequestID", (string)null)); break; // invoke 'remove' verb on the file to remove it from Quick Access // note: for folders, we need to use the verb 'unpinfromhome' or 'removefromhome' case "UnpinFile": var unpinFileResponse = await Win32API.StartSTATask(() => { try { var path = (string)message["Path"]; var command = $"-command \"((New-Object -ComObject Shell.Application).Namespace('shell:{QuickAccessGuid}\').Items() " + $"| Where-Object {{ $_.Path -eq '{path}' }}).InvokeVerb('remove')\""; bool success = Win32API.RunPowershellCommand(command, false); response.Add("UnpinFile", path); response.Add("Success", success); } catch (Exception e) { Program.Logger.Warn(e); } return(response); }); await Win32API.SendMessageAsync(connection, unpinFileResponse, message.Get("RequestID", (string)null)); break; } }