From 852750d1c6b05080334fa0b96f954da379d490e1 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Thu, 2 Jul 2020 23:44:48 +0300 Subject: [PATCH 01/15] start off the ProcessKiller plugin This plugin is a direct port of Wox.Plugin.ProcessKiller from https://github.com/theClueless/Wox.Plugins --- Flow.Launcher.sln | 15 ++ .../Flow.Launcher.Plugin.ProcessKiller.csproj | 50 +++++ .../Images/app.png | Bin 0 -> 1338 bytes .../Main.cs | 203 ++++++++++++++++++ .../plugin.json | 12 ++ 5 files changed, 280 insertions(+) create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/Images/app.png create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln index 2be28daf1..43c012b5b 100644 --- a/Flow.Launcher.sln +++ b/Flow.Launcher.sln @@ -70,6 +70,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Calcul EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Explorer", "Plugins\Flow.Launcher.Plugin.Explorer\Flow.Launcher.Plugin.Explorer.csproj", "{F9C4C081-4CC3-4146-95F1-E102B4E10A5F}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.ProcessKiller", "Plugins\Flow.Launcher.Plugin.ProcessKiller\Flow.Launcher.Plugin.ProcessKiller.csproj", "{588088F4-3262-4F9F-9663-A05DE12534C3}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -297,6 +299,18 @@ Global {F9C4C081-4CC3-4146-95F1-E102B4E10A5F}.Release|x64.Build.0 = Release|Any CPU {F9C4C081-4CC3-4146-95F1-E102B4E10A5F}.Release|x86.ActiveCfg = Release|Any CPU {F9C4C081-4CC3-4146-95F1-E102B4E10A5F}.Release|x86.Build.0 = Release|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x64.ActiveCfg = Debug|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x64.Build.0 = Debug|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x86.ActiveCfg = Debug|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x86.Build.0 = Debug|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Release|Any CPU.Build.0 = Release|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x64.ActiveCfg = Release|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x64.Build.0 = Release|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x86.ActiveCfg = Release|Any CPU + {588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -315,6 +329,7 @@ Global {9B130CC5-14FB-41FF-B310-0A95B6894C37} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {59BD9891-3837-438A-958D-ADC7F91F6F7E} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} {F9C4C081-4CC3-4146-95F1-E102B4E10A5F} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} + {588088F4-3262-4F9F-9663-A05DE12534C3} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {F26ACB50-3F6C-4907-B0C9-1ADACC1D0DED} diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj new file mode 100644 index 000000000..1fb5d2a69 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -0,0 +1,50 @@ + + + + netcoreapp3.1 + Flow.Launcher.Plugin.ProcessKiller + Flow.Launcher.Plugin.ProcessKiller + Flow-Launcher + https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller + https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller + flow-launcher flow-plugin + false + false + + + + true + full + false + ..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.ProcessKiller\ + DEBUG;TRACE + prompt + 4 + false + + + + pdbonly + true + ..\..\Output\Release\Plugins\Flow.Launcher.Plugin.ProcessKiller\ + TRACE + prompt + 4 + false + + + + + PreserveNewest + + + Always + + + + + + + + + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Images/app.png b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Images/app.png new file mode 100644 index 0000000000000000000000000000000000000000..fa76a5d294201ec0a83a07dd3b1a8b157393929a GIT binary patch literal 1338 zcmV-A1;zS_P)WEcectC&=5#tqAXHgdi9J%-p8x=y2tyt4XTVw#82ttOBk%|SpZVJ8Qvd+}9EMlG zVI)LKOH1n>7#J|Z<3hj!0B|-B{1Lq#7Z=AA7Z)q?^YaxE5fLOgIa$sy3^_eLWi1v9 zF&d5b<>h7j#l?jK_eV!Z%li8I)ba80WOsMBB_}86rC$L6yby*TfIk%0GBPscwY9aX ztgI|~Ag4Y!IAEuzr)@f&PNmgq8C-KX9AtZY`(<8U-dA1)0Pq|beg^&k=Xkohx;j-w zMMcP0K-1&nqocRC_v8NleuJ>4knH(Z01pojm$kICJj>0^Re1W@-Q68Ao6X#_TrMYx ziHSbJA08f@?d|QBv$L~rU|Q^^0XY4qFnrHRrBINrt}bb90mI?d|zh^VQWASy&JoJZcE8 zQAsVm0!*z-03bau3PDm*Qkb%`vM?z)o_Kh8nC$HA_yivu9OQz|+}xb#U1@2lQewn< zsQ?_+)YPcZ_$Z6!z|o3Pm7}Ah9)%FVpPrt$`TYDmSz1~W?ZJOb1(3t(vS9pD@bmim z`e*b<8jXgWpP!T4+gomqHUsWNY&M(A2yqSVK>+9fMXIW*h)VSjW^8OMv%0!!M}vf^ zYHDigcRcDR!iK`aLN}vRDwRa9*OSc5Op#Fu0wGzgRyXj*#zszfDHRnJ(O&g};S-Ce zmp+B?M!vw23JMBnjORE>6=n$u2@Jitqoae|-`@unY;JCDNLyQ*XboKyT@?x91&xu0 zlUVA$W#m7m$jC?g^gA%tgdBnW|q2*xaW zXD}GvLprBzY{ZofK@}z#z7XC(#A0HpHLqkLK>6?Ud zU0M?w_~yfJNfs#W@9(ocJv|nv2L+(F0PZTuq>&J{z@<4Tvz?utotD|zSzD;!i;Iiz zTU%Sr6gX<3Dd@5sE1Bx*>VV5~RQcrOqz!5W+M^zUb#VIMLT*ejN|uzAD4@aM8k5x2 zR8Al$SR4>1oan-IV?xoNs9gXz2HTp|@q+vt`Wk@03#m7hG^aXD=Rq{5Kk?1!yO5hx w5A8WtPo-3QE@T|6*G+t0c^yo9{ _systemProcessList = new HashSet(){ + "conhost", + "svchost", + "idle", + "system", + "rundll32", + "csrss", + "lsass", + "lsm", + "smss", + "wininit", + "winlogon", + "services", + "spoolsv", + "explorer"}; + + public List Query(Query query) + { + var termToSearch = query.Terms.Length == 1 + ? null + : query.FirstSearch.ToLower(); + var processlist = GetProcesslist(termToSearch); + + return + !processlist.Any() + ? null + : CreateResultsFromProcesses(processlist, termToSearch); + } + + private List CreateResultsFromProcesses(List processlist, string termToSearch) + { + var results = new List(); + + foreach (var pr in processlist) + { + var p = pr.Process; + var path = GetPath(p); + results.Add(new Result() + { + IcoPath = path, + Title = p.ProcessName + " - " + p.Id, + SubTitle = path, + Score = pr.Score, + Action = (c) => + { + KillProcess(p); + return true; + } + }); + } + + if (processlist.Count > 1 && !string.IsNullOrEmpty(termToSearch)) + { + results.Insert(0, new Result() + { + IcoPath = "Images\\app.png", + Title = "kill all \"" + termToSearch + "\" process", + SubTitle = "", + Score = 200, + Action = (c) => + { + foreach (var p in processlist) + { + KillProcess(p.Process); + } + + return true; + } + }); + } + + return results; + + void KillProcess(Process p) + { + try + { + if (!p.HasExited) + { + p.Kill(); + } + } + catch (Exception e) + { + Log.Exception($"Fail to kill process {p.ProcessName}", e); + } + } + } + private List GetProcesslist(string termToSearch) + { + var processlist = new List(); + var processes = Process.GetProcesses(); + if (string.IsNullOrWhiteSpace(termToSearch)) + { + // show all process + foreach (var p in processes) + { + if (FilterSystemProcesses(p)) continue; + + processlist.Add(new ProcessResult(p,0)); + } + } + else + { + foreach (var p in processes) + { + if (FilterSystemProcesses(p)) continue; + var score = StringMatcher.FuzzySearch(termToSearch, p.ProcessName + p.Id).Score; + if (score > 0) + { + processlist.Add(new ProcessResult(p, score)); + } + } + } + + return processlist; + + bool FilterSystemProcesses(Process p) + { + var name = p.ProcessName.ToLower(); + if (_systemProcessList.Contains(name)) + return true; + return false; + } + } + + internal class ProcessResult + { + public ProcessResult(Process process, int score) + { + Process = process; + Score = score; + } + + public Process Process { get; } + + public int Score { get; } + } + + private string GetPath(Process p) + { + try + { + var path = GetProcessFilename(p); + return path.ToLower(); + } + catch + { + return ""; + } + } + + public void Init(PluginInitContext context) + { + } + + [Flags] + private enum ProcessAccessFlags : uint + { + QueryLimitedInformation = 0x00001000 + } + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool QueryFullProcessImageName( + [In] IntPtr hProcess, + [In] int dwFlags, + [Out] StringBuilder lpExeName, + ref int lpdwSize); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr OpenProcess( + ProcessAccessFlags processAccess, + bool bInheritHandle, + int processId); + + private string GetProcessFilename(Process p) + { + int capacity = 2000; + StringBuilder builder = new StringBuilder(capacity); + IntPtr ptr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, p.Id); + if (!QueryFullProcessImageName(ptr, 0, builder, ref capacity)) + { + return String.Empty; + } + + return builder.ToString(); + } + } +} diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json b/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json new file mode 100644 index 000000000..f2e1eca12 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/plugin.json @@ -0,0 +1,12 @@ +{ + "ID":"b64d0a79-329a-48b0-b53f-d658318a1bf6", + "ActionKeyword":"kill", + "Name":"Process Killer", + "Description":"kill running processes from Flow", + "Author":"Flow-Launcher", + "Version":"1.0.0", + "Language":"csharp", + "Website":"https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller", + "IcoPath":"Images\\app.png", + "ExecuteFileName":"Flow.Launcher.Plugin.ProcessKiller.dll" +} \ No newline at end of file From 1707ec722214127b2df0b9b9660205e7fdb4a96d Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 00:16:11 +0300 Subject: [PATCH 02/15] ProcessKiller: quick refactoring --- .../Main.cs | 28 ++++++++----------- 1 file changed, 11 insertions(+), 17 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 919f1e135..36b46e856 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -68,7 +68,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller results.Insert(0, new Result() { IcoPath = "Images\\app.png", - Title = "kill all \"" + termToSearch + "\" process", + Title = "kill all \"" + termToSearch + "\" processes", SubTitle = "", Score = 200, Action = (c) => @@ -96,29 +96,25 @@ namespace Flow.Launcher.Plugin.ProcessKiller } catch (Exception e) { - Log.Exception($"Fail to kill process {p.ProcessName}", e); + Log.Exception($"|ProcessKiller.CreateResultsFromProcesses|Failed to kill process {p.ProcessName}", e); } } } private List GetProcesslist(string termToSearch) { var processlist = new List(); - var processes = Process.GetProcesses(); - if (string.IsNullOrWhiteSpace(termToSearch)) - { - // show all process - foreach (var p in processes) - { - if (FilterSystemProcesses(p)) continue; + foreach (var p in Process.GetProcesses()) + { + if (FilterSystemProcesses(p)) continue; + + if (string.IsNullOrWhiteSpace(termToSearch)) + { + // show all non-system processes processlist.Add(new ProcessResult(p,0)); } - } - else - { - foreach (var p in processes) + else { - if (FilterSystemProcesses(p)) continue; var score = StringMatcher.FuzzySearch(termToSearch, p.ProcessName + p.Id).Score; if (score > 0) { @@ -132,9 +128,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller bool FilterSystemProcesses(Process p) { var name = p.ProcessName.ToLower(); - if (_systemProcessList.Contains(name)) - return true; - return false; + return _systemProcessList.Contains(name); } } From d0e196cfed9c5caacba4c076803b454e46c644cd Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 00:18:15 +0300 Subject: [PATCH 03/15] ProcessKiller: highlight result title --- Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 36b46e856..9f82dfe16 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -54,6 +54,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller IcoPath = path, Title = p.ProcessName + " - " + p.Id, SubTitle = path, + TitleHighlightData = StringMatcher.FuzzySearch(termToSearch, p.ProcessName).MatchData, Score = pr.Score, Action = (c) => { From a52575cc1773e2ebbbf10c1adf0fb11333af4627 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 00:34:10 +0300 Subject: [PATCH 04/15] ProcessKiller: do not convert paths to lower-case for consistency with other plugins --- Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 9f82dfe16..883b5c493 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -150,8 +150,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller { try { - var path = GetProcessFilename(p); - return path.ToLower(); + return GetProcessFilename(p); } catch { From 563bf4d797a51ada0b776b034e6b90ef13adc6fd Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 01:16:33 +0300 Subject: [PATCH 05/15] ProcessKiller: add i18n support --- .../Flow.Launcher.Plugin.ProcessKiller.csproj | 5 ++++ .../Languages/en.xaml | 10 ++++++++ .../Main.cs | 25 ++++++++++++++----- 3 files changed, 34 insertions(+), 6 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj index 1fb5d2a69..ab84aa54a 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Flow.Launcher.Plugin.ProcessKiller.csproj @@ -37,6 +37,11 @@ PreserveNewest + + Designer + MSBuild:Compile + PreserveNewest + Always diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml new file mode 100644 index 000000000..13655f998 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml @@ -0,0 +1,10 @@ + + + Process Killer + Kill running processes from Flow Launcher + + kill all "{0}" processes + + \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 883b5c493..e22fad609 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -10,7 +10,7 @@ using Flow.Launcher.Infrastructure.Logger; namespace Flow.Launcher.Plugin.ProcessKiller { - public class Main : IPlugin + public class Main : IPlugin, IPluginI18n { private readonly HashSet _systemProcessList = new HashSet(){ "conhost", @@ -28,6 +28,13 @@ namespace Flow.Launcher.Plugin.ProcessKiller "spoolsv", "explorer"}; + private static PluginInitContext _context; + + public void Init(PluginInitContext context) + { + _context = context; + } + public List Query(Query query) { var termToSearch = query.Terms.Length == 1 @@ -41,6 +48,16 @@ namespace Flow.Launcher.Plugin.ProcessKiller : CreateResultsFromProcesses(processlist, termToSearch); } + public string GetTranslatedPluginTitle() + { + return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_name"); + } + + public string GetTranslatedPluginDescription() + { + return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_description"); + } + private List CreateResultsFromProcesses(List processlist, string termToSearch) { var results = new List(); @@ -69,7 +86,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller results.Insert(0, new Result() { IcoPath = "Images\\app.png", - Title = "kill all \"" + termToSearch + "\" processes", + Title = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all"), termToSearch), SubTitle = "", Score = 200, Action = (c) => @@ -158,10 +175,6 @@ namespace Flow.Launcher.Plugin.ProcessKiller } } - public void Init(PluginInitContext context) - { - } - [Flags] private enum ProcessAccessFlags : uint { From 10ce003dac6c3b7e86fea41da607e49087422a04 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 02:10:41 +0300 Subject: [PATCH 06/15] ProcessKiller: change condition for batch kill To avoid killing processes by mistake, only give the option to kill all displayed processes when they are all instances of the same executable. --- Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index e22fad609..d504ce842 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -81,7 +81,10 @@ namespace Flow.Launcher.Plugin.ProcessKiller }); } - if (processlist.Count > 1 && !string.IsNullOrEmpty(termToSearch)) + // When there are multiple results AND all of them are instances of the same executable + // add a quick option to kill them all at the top of the results. + var firstResult = results.FirstOrDefault()?.SubTitle; + if (processlist.Count > 1 && !string.IsNullOrEmpty(termToSearch) && results.All(r => r.SubTitle == firstResult)) { results.Insert(0, new Result() { From 6e6a74beb9b02a3da1c61eb7c52909ccfc72bf7d Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 02:43:35 +0300 Subject: [PATCH 07/15] ProcessKiller: add context menu option to kill all processes whose file path matches with the selected result. --- .../Languages/en.xaml | 1 + .../Main.cs | 61 +++++++++++++------ 2 files changed, 44 insertions(+), 18 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml index 13655f998..2eee31745 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml @@ -6,5 +6,6 @@ Kill running processes from Flow Launcher kill all "{0}" processes + kill all instances \ No newline at end of file diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index d504ce842..e51d480c5 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -10,7 +10,7 @@ using Flow.Launcher.Infrastructure.Logger; namespace Flow.Launcher.Plugin.ProcessKiller { - public class Main : IPlugin, IPluginI18n + public class Main : IPlugin, IPluginI18n, IContextMenu { private readonly HashSet _systemProcessList = new HashSet(){ "conhost", @@ -58,6 +58,34 @@ namespace Flow.Launcher.Plugin.ProcessKiller return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_description"); } + public List LoadContextMenus(Result result) + { + var menuOptions = new List(); + var processPath = result.SubTitle; + + // get all non-system processes whose file path matches that of the given result (processPath) + var similarProcesses = Process.GetProcesses() + .Where(p => !IsSystemProcess(p) && GetProcessFilename(p) == processPath); + + menuOptions.Add(new Result + { + Title = _context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_instances"), + SubTitle = processPath, + Action = _ => + { + foreach (var p in similarProcesses) + { + KillProcess(p); + } + + return true; + }, + IcoPath = "Images/app.png" + }); + + return menuOptions; + } + private List CreateResultsFromProcesses(List processlist, string termToSearch) { var results = new List(); @@ -105,29 +133,30 @@ namespace Flow.Launcher.Plugin.ProcessKiller } return results; + } - void KillProcess(Process p) + private void KillProcess(Process p) + { + try { - try + if (!p.HasExited) { - if (!p.HasExited) - { - p.Kill(); - } - } - catch (Exception e) - { - Log.Exception($"|ProcessKiller.CreateResultsFromProcesses|Failed to kill process {p.ProcessName}", e); + p.Kill(); } } + catch (Exception e) + { + Log.Exception($"|ProcessKiller.CreateResultsFromProcesses|Failed to kill process {p.ProcessName}", e); + } } + private List GetProcesslist(string termToSearch) { var processlist = new List(); foreach (var p in Process.GetProcesses()) { - if (FilterSystemProcesses(p)) continue; + if (IsSystemProcess(p)) continue; if (string.IsNullOrWhiteSpace(termToSearch)) { @@ -145,14 +174,10 @@ namespace Flow.Launcher.Plugin.ProcessKiller } return processlist; - - bool FilterSystemProcesses(Process p) - { - var name = p.ProcessName.ToLower(); - return _systemProcessList.Contains(name); - } } + private bool IsSystemProcess(Process p) => _systemProcessList.Contains(p.ProcessName.ToLower()); + internal class ProcessResult { public ProcessResult(Process process, int score) From 12281142c1493849015cefc6ccbf6993182d6ae7 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 15:44:13 +0300 Subject: [PATCH 08/15] ProcessKiller: support spaces in process search --- Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index e51d480c5..1a71572be 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -37,15 +37,15 @@ namespace Flow.Launcher.Plugin.ProcessKiller public List Query(Query query) { - var termToSearch = query.Terms.Length == 1 + var termToSearch = query.Terms.Length <= 1 ? null - : query.FirstSearch.ToLower(); + : string.Join(Plugin.Query.TermSeperater, query.Terms.Skip(1)).ToLower(); + var processlist = GetProcesslist(termToSearch); - return - !processlist.Any() - ? null - : CreateResultsFromProcesses(processlist, termToSearch); + return !processlist.Any() + ? null + : CreateResultsFromProcesses(processlist, termToSearch); } public string GetTranslatedPluginTitle() From e2bef827db0de5bfae5441329c3ff951d8267630 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 17:07:24 +0300 Subject: [PATCH 09/15] ProcessKiller: split source to multiple files --- .../Main.cs | 131 ++---------------- .../ProcessHelper.cs | 125 +++++++++++++++++ .../ProcessResult.cs | 17 +++ 3 files changed, 150 insertions(+), 123 deletions(-) create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 1a71572be..39d659f39 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -12,21 +12,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller { public class Main : IPlugin, IPluginI18n, IContextMenu { - private readonly HashSet _systemProcessList = new HashSet(){ - "conhost", - "svchost", - "idle", - "system", - "rundll32", - "csrss", - "lsass", - "lsm", - "smss", - "wininit", - "winlogon", - "services", - "spoolsv", - "explorer"}; + private ProcessHelper processHelper = new ProcessHelper(); private static PluginInitContext _context; @@ -41,7 +27,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller ? null : string.Join(Plugin.Query.TermSeperater, query.Terms.Skip(1)).ToLower(); - var processlist = GetProcesslist(termToSearch); + var processlist = processHelper.GetMatchingProcesses(termToSearch); return !processlist.Any() ? null @@ -64,8 +50,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller var processPath = result.SubTitle; // get all non-system processes whose file path matches that of the given result (processPath) - var similarProcesses = Process.GetProcesses() - .Where(p => !IsSystemProcess(p) && GetProcessFilename(p) == processPath); + var similarProcesses = processHelper.GetSimilarProcesses(processPath); menuOptions.Add(new Result { @@ -75,7 +60,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller { foreach (var p in similarProcesses) { - KillProcess(p); + processHelper.TryKill(p); } return true; @@ -93,7 +78,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller foreach (var pr in processlist) { var p = pr.Process; - var path = GetPath(p); + var path = processHelper.TryGetProcessFilename(p); results.Add(new Result() { IcoPath = path, @@ -103,7 +88,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller Score = pr.Score, Action = (c) => { - KillProcess(p); + processHelper.TryKill(p); return true; } }); @@ -116,7 +101,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller { results.Insert(0, new Result() { - IcoPath = "Images\\app.png", + IcoPath = "Images/app.png", Title = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all"), termToSearch), SubTitle = "", Score = 200, @@ -124,7 +109,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller { foreach (var p in processlist) { - KillProcess(p.Process); + processHelper.TryKill(p.Process); } return true; @@ -134,105 +119,5 @@ namespace Flow.Launcher.Plugin.ProcessKiller return results; } - - private void KillProcess(Process p) - { - try - { - if (!p.HasExited) - { - p.Kill(); - } - } - catch (Exception e) - { - Log.Exception($"|ProcessKiller.CreateResultsFromProcesses|Failed to kill process {p.ProcessName}", e); - } - } - - private List GetProcesslist(string termToSearch) - { - var processlist = new List(); - - foreach (var p in Process.GetProcesses()) - { - if (IsSystemProcess(p)) continue; - - if (string.IsNullOrWhiteSpace(termToSearch)) - { - // show all non-system processes - processlist.Add(new ProcessResult(p,0)); - } - else - { - var score = StringMatcher.FuzzySearch(termToSearch, p.ProcessName + p.Id).Score; - if (score > 0) - { - processlist.Add(new ProcessResult(p, score)); - } - } - } - - return processlist; - } - - private bool IsSystemProcess(Process p) => _systemProcessList.Contains(p.ProcessName.ToLower()); - - internal class ProcessResult - { - public ProcessResult(Process process, int score) - { - Process = process; - Score = score; - } - - public Process Process { get; } - - public int Score { get; } - } - - private string GetPath(Process p) - { - try - { - return GetProcessFilename(p); - } - catch - { - return ""; - } - } - - [Flags] - private enum ProcessAccessFlags : uint - { - QueryLimitedInformation = 0x00001000 - } - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern bool QueryFullProcessImageName( - [In] IntPtr hProcess, - [In] int dwFlags, - [Out] StringBuilder lpExeName, - ref int lpdwSize); - - [DllImport("kernel32.dll", SetLastError = true)] - private static extern IntPtr OpenProcess( - ProcessAccessFlags processAccess, - bool bInheritHandle, - int processId); - - private string GetProcessFilename(Process p) - { - int capacity = 2000; - StringBuilder builder = new StringBuilder(capacity); - IntPtr ptr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, p.Id); - if (!QueryFullProcessImageName(ptr, 0, builder, ref capacity)) - { - return String.Empty; - } - - return builder.ToString(); - } } } diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs new file mode 100644 index 000000000..16a8687e6 --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs @@ -0,0 +1,125 @@ +using Flow.Launcher.Infrastructure; +using Flow.Launcher.Infrastructure.Logger; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Runtime.InteropServices; +using System.Text; + +namespace Flow.Launcher.Plugin.ProcessKiller +{ + internal class ProcessHelper + { + private readonly HashSet _systemProcessList = new HashSet() + { + "conhost", + "svchost", + "idle", + "system", + "rundll32", + "csrss", + "lsass", + "lsm", + "smss", + "wininit", + "winlogon", + "services", + "spoolsv", + "explorer" + }; + + private bool IsSystemProcess(Process p) => _systemProcessList.Contains(p.ProcessName.ToLower()); + + /// + /// Returns a ProcessResult for evey running non-system process whose name matches the given searchTerm + /// + public List GetMatchingProcesses(string searchTerm) + { + var processlist = new List(); + + foreach (var p in Process.GetProcesses()) + { + if (IsSystemProcess(p)) continue; + + if (string.IsNullOrWhiteSpace(searchTerm)) + { + // show all non-system processes + processlist.Add(new ProcessResult(p, 0)); + } + else + { + var score = StringMatcher.FuzzySearch(searchTerm, p.ProcessName + p.Id).Score; + if (score > 0) + { + processlist.Add(new ProcessResult(p, score)); + } + } + } + + return processlist; + } + + /// + /// Returns all non-system processes whose file path matches the given processPath + /// + public IEnumerable GetSimilarProcesses(string processPath) + { + return Process.GetProcesses().Where(p => !IsSystemProcess(p) && TryGetProcessFilename(p) == processPath); + } + + public void TryKill(Process p) + { + try + { + if (!p.HasExited) + { + p.Kill(); + } + } + catch (Exception e) + { + Log.Exception($"|ProcessKiller.CreateResultsFromProcesses|Failed to kill process {p.ProcessName}", e); + } + } + + public string TryGetProcessFilename(Process p) + { + try + { + int capacity = 2000; + StringBuilder builder = new StringBuilder(capacity); + IntPtr ptr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, p.Id); + if (!QueryFullProcessImageName(ptr, 0, builder, ref capacity)) + { + return String.Empty; + } + + return builder.ToString(); + } + catch + { + return ""; + } + } + + [Flags] + private enum ProcessAccessFlags : uint + { + QueryLimitedInformation = 0x00001000 + } + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern bool QueryFullProcessImageName( + [In] IntPtr hProcess, + [In] int dwFlags, + [Out] StringBuilder lpExeName, + ref int lpdwSize); + + [DllImport("kernel32.dll", SetLastError = true)] + private static extern IntPtr OpenProcess( + ProcessAccessFlags processAccess, + bool bInheritHandle, + int processId); + } +} diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs new file mode 100644 index 000000000..03856677e --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessResult.cs @@ -0,0 +1,17 @@ +using System.Diagnostics; + +namespace Flow.Launcher.Plugin.ProcessKiller +{ + internal class ProcessResult + { + public ProcessResult(Process process, int score) + { + Process = process; + Score = score; + } + + public Process Process { get; } + + public int Score { get; } + } +} \ No newline at end of file From 2c5305827cdab394dddc58661b2d4dd06c8707ef Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 17:11:18 +0300 Subject: [PATCH 10/15] ProcessKiller: use process icon in context menu --- Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs index 39d659f39..22c84b20f 100644 --- a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs @@ -65,7 +65,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller return true; }, - IcoPath = "Images/app.png" + IcoPath = processPath }); return menuOptions; From daa112e0879814e0645db7980e48cdfb7e4fd17d Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Fri, 3 Jul 2020 17:34:44 +0300 Subject: [PATCH 11/15] ProcessKiller: add a readme --- Plugins/Flow.Launcher.Plugin.ProcessKiller/Readme.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 Plugins/Flow.Launcher.Plugin.ProcessKiller/Readme.md diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Readme.md b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Readme.md new file mode 100644 index 000000000..3307c917e --- /dev/null +++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Readme.md @@ -0,0 +1,8 @@ +Process Killer Plugin +===================== + +A Flow-Launcher plugin that allows you to kill running processes. + +Based on Wox.Plugin.ProcessKiller, originally created by [cxfksword](https://github.com/cxfksword/Wox.Plugin.ProcessKiller) and improved by [theClueless](https://github.com/theClueless/Wox.Plugins/tree/master/Wox.Plugin.ProcessKiller). + +![image](https://user-images.githubusercontent.com/697917/86478286-b4697700-bd52-11ea-875a-b3b90fa34bf2.png) From 4961bf3138808fdc7b41ec8af9f3f787d5745d4b Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 4 Jul 2020 18:02:39 +1000 Subject: [PATCH 12/15] bump version for release Explorer, Plugin, Flow Launcher --- Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj | 8 ++++---- Plugins/Flow.Launcher.Plugin.Explorer/plugin.json | 2 +- SolutionAssemblyInfo.cs | 6 +++--- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj index b97bffd45..0c69a6b9b 100644 --- a/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj +++ b/Flow.Launcher.Plugin/Flow.Launcher.Plugin.csproj @@ -14,10 +14,10 @@ - 1.0.0 - 1.0.0 - 1.0.0 - 1.0.0 + 1.1.0 + 1.1.0 + 1.1.0 + 1.1.0 Flow.Launcher.Plugin Flow-Launcher MIT diff --git a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json index 10b3edd96..91b27edb1 100644 --- a/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json +++ b/Plugins/Flow.Launcher.Plugin.Explorer/plugin.json @@ -4,7 +4,7 @@ "Name": "Explorer", "Description": "Search and manage files and folders. Explorer utilises Windows Index Search", "Author": "Jeremy Wu", - "Version": "1.0.0", + "Version": "1.1.0", "Language": "csharp", "Website": "https://github.com/Flow-Launcher/Flow.Launcher", "ExecuteFileName": "Flow.Launcher.Plugin.Explorer.dll", diff --git a/SolutionAssemblyInfo.cs b/SolutionAssemblyInfo.cs index 1482bce9e..b810bb8a9 100644 --- a/SolutionAssemblyInfo.cs +++ b/SolutionAssemblyInfo.cs @@ -16,6 +16,6 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.0.0")] -[assembly: AssemblyFileVersion("1.0.0")] -[assembly: AssemblyInformationalVersion("1.0.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.1.0")] +[assembly: AssemblyFileVersion("1.1.0")] +[assembly: AssemblyInformationalVersion("1.1.0")] \ No newline at end of file From 956ab1fd9311e321933fcbcd2cf8d64a6ad2252c Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sat, 4 Jul 2020 18:17:05 +1000 Subject: [PATCH 13/15] update appveyor version --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a4000d1a4..c69ae3fb0 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: '1.0.0.{build}' +version: '1.1.0.{build}' init: - ps: | From 755add2518e0be769bf6de3196ac0c7f2ee48bbc Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Sat, 4 Jul 2020 18:48:22 +0300 Subject: [PATCH 14/15] fix build order in solution file Make the `Flow.Launcher` project depend on the `ProcessKiller` project. Currently, `Flow.Launcher` is built before the `ProcessKiller` plugin, and therefore gets packaged (post-build script) without it. --- Flow.Launcher.sln | 1 + 1 file changed, 1 insertion(+) diff --git a/Flow.Launcher.sln b/Flow.Launcher.sln index 43c012b5b..70155a8a0 100644 --- a/Flow.Launcher.sln +++ b/Flow.Launcher.sln @@ -26,6 +26,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher", "Flow.Launc {A3DCCBCA-ACC1-421D-B16E-210896234C26} = {A3DCCBCA-ACC1-421D-B16E-210896234C26} {049490F0-ECD2-4148-9B39-2135EC346EBE} = {049490F0-ECD2-4148-9B39-2135EC346EBE} {403B57F2-1856-4FC7-8A24-36AB346B763E} = {403B57F2-1856-4FC7-8A24-36AB346B763E} + {588088F4-3262-4F9F-9663-A05DE12534C3} = {588088F4-3262-4F9F-9663-A05DE12534C3} EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Infrastructure", "Flow.Launcher.Infrastructure\Flow.Launcher.Infrastructure.csproj", "{4FD29318-A8AB-4D8F-AA47-60BC241B8DA3}" From 2e8d6a18b644153a0bf0aa0653ac8d9093388809 Mon Sep 17 00:00:00 2001 From: Jeremy Wu Date: Sun, 5 Jul 2020 12:35:14 +1000 Subject: [PATCH 15/15] version 1.1.1 --- SolutionAssemblyInfo.cs | 6 +++--- appveyor.yml | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/SolutionAssemblyInfo.cs b/SolutionAssemblyInfo.cs index b810bb8a9..9dce85a1e 100644 --- a/SolutionAssemblyInfo.cs +++ b/SolutionAssemblyInfo.cs @@ -16,6 +16,6 @@ using System.Runtime.InteropServices; [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: AssemblyVersion("1.1.0")] -[assembly: AssemblyFileVersion("1.1.0")] -[assembly: AssemblyInformationalVersion("1.1.0")] \ No newline at end of file +[assembly: AssemblyVersion("1.1.1")] +[assembly: AssemblyFileVersion("1.1.1")] +[assembly: AssemblyInformationalVersion("1.1.1")] \ No newline at end of file diff --git a/appveyor.yml b/appveyor.yml index c69ae3fb0..81057e43a 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,4 +1,4 @@ -version: '1.1.0.{build}' +version: '1.1.1.{build}' init: - ps: |