From 852750d1c6b05080334fa0b96f954da379d490e1 Mon Sep 17 00:00:00 2001 From: Ioannis G Date: Thu, 2 Jul 2020 23:44:48 +0300 Subject: [PATCH] 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