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 000000000..fa76a5d29
Binary files /dev/null and b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Images/app.png differ
diff --git a/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs
new file mode 100644
index 000000000..919f1e135
--- /dev/null
+++ b/Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs
@@ -0,0 +1,203 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Diagnostics;
+using System.Dynamic;
+using System.Runtime.InteropServices;
+using Flow.Launcher.Infrastructure;
+using Flow.Launcher.Infrastructure.Logger;
+
+namespace Flow.Launcher.Plugin.ProcessKiller
+{
+ public class Main : IPlugin
+ {
+ private readonly HashSet _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