public async Task ParseArgumentsAsync(NamedPipeServerStream connection, Dictionary <string, object> message, string arguments) { switch (arguments) { case "LoadContextMenu": var contextMenuResponse = new ValueSet(); var loadThreadWithMessageQueue = new ThreadWithMessageQueue <Dictionary <string, object> >(HandleMenuMessage); var cMenuLoad = await loadThreadWithMessageQueue.PostMessageAsync <ContextMenu>(message); contextMenuResponse.Add("Handle", handleTable.AddValue(loadThreadWithMessageQueue)); contextMenuResponse.Add("ContextMenu", JsonConvert.SerializeObject(cMenuLoad)); var serializedCm = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(contextMenuResponse)); await Win32API.SendMessageAsync(connection, contextMenuResponse, message.Get("RequestID", (string)null)); break; case "ExecAndCloseContextMenu": var menuKey = (string)message["Handle"]; var execThreadWithMessageQueue = handleTable.GetValue <ThreadWithMessageQueue <Dictionary <string, object> > >(menuKey); if (execThreadWithMessageQueue != null) { await execThreadWithMessageQueue.PostMessage(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)message["FilePath"]; var split = filePath.Split('|').Where(x => !string.IsNullOrWhiteSpace(x)); var verb = (string)message["Verb"]; using (var cMenu = ContextMenu.GetContextMenuForFiles(split.ToArray(), Shell32.CMF.CMF_DEFAULTONLY)) { var result = cMenu?.InvokeVerb(verb); await Win32API.SendMessageAsync(connection, new ValueSet() { { "Success", result } }, message.Get("RequestID", (string)null)); } break; } }