Skip to content

Commit a828e9c

Browse files
authored
Merge pull request #103 from JohnTheGr8/plugin_process_killer
Add plugin: Process Killer
2 parents 8f74316 + daa112e commit a828e9c

File tree

9 files changed

+366
-0
lines changed

9 files changed

+366
-0
lines changed

Flow.Launcher.sln

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Flow.Launcher.Plugin.Calcul
7070
EndProject
7171
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}"
7272
EndProject
73+
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}"
74+
EndProject
7375
Global
7476
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7577
Debug|Any CPU = Debug|Any CPU
@@ -297,6 +299,18 @@ Global
297299
{F9C4C081-4CC3-4146-95F1-E102B4E10A5F}.Release|x64.Build.0 = Release|Any CPU
298300
{F9C4C081-4CC3-4146-95F1-E102B4E10A5F}.Release|x86.ActiveCfg = Release|Any CPU
299301
{F9C4C081-4CC3-4146-95F1-E102B4E10A5F}.Release|x86.Build.0 = Release|Any CPU
302+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
303+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
304+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x64.ActiveCfg = Debug|Any CPU
305+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x64.Build.0 = Debug|Any CPU
306+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x86.ActiveCfg = Debug|Any CPU
307+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Debug|x86.Build.0 = Debug|Any CPU
308+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
309+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Release|Any CPU.Build.0 = Release|Any CPU
310+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x64.ActiveCfg = Release|Any CPU
311+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x64.Build.0 = Release|Any CPU
312+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x86.ActiveCfg = Release|Any CPU
313+
{588088F4-3262-4F9F-9663-A05DE12534C3}.Release|x86.Build.0 = Release|Any CPU
300314
EndGlobalSection
301315
GlobalSection(SolutionProperties) = preSolution
302316
HideSolutionNode = FALSE
@@ -315,6 +329,7 @@ Global
315329
{9B130CC5-14FB-41FF-B310-0A95B6894C37} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
316330
{59BD9891-3837-438A-958D-ADC7F91F6F7E} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
317331
{F9C4C081-4CC3-4146-95F1-E102B4E10A5F} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
332+
{588088F4-3262-4F9F-9663-A05DE12534C3} = {3A73F5A7-0335-40D8-BF7C-F20BE5D0BA87}
318333
EndGlobalSection
319334
GlobalSection(ExtensibilityGlobals) = postSolution
320335
SolutionGuid = {F26ACB50-3F6C-4907-B0C9-1ADACC1D0DED}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<Project Sdk="Microsoft.NET.Sdk">
2+
3+
<PropertyGroup>
4+
<TargetFramework>netcoreapp3.1</TargetFramework>
5+
<AssemblyName>Flow.Launcher.Plugin.ProcessKiller</AssemblyName>
6+
<PackageId>Flow.Launcher.Plugin.ProcessKiller</PackageId>
7+
<Authors>Flow-Launcher</Authors>
8+
<PackageProjectUrl>https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller</PackageProjectUrl>
9+
<RepositoryUrl>https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller</RepositoryUrl>
10+
<PackageTags>flow-launcher flow-plugin</PackageTags>
11+
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
12+
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
13+
</PropertyGroup>
14+
15+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
16+
<DebugSymbols>true</DebugSymbols>
17+
<DebugType>full</DebugType>
18+
<Optimize>false</Optimize>
19+
<OutputPath>..\..\Output\Debug\Plugins\Flow.Launcher.Plugin.ProcessKiller\</OutputPath>
20+
<DefineConstants>DEBUG;TRACE</DefineConstants>
21+
<ErrorReport>prompt</ErrorReport>
22+
<WarningLevel>4</WarningLevel>
23+
<Prefer32Bit>false</Prefer32Bit>
24+
</PropertyGroup>
25+
26+
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
27+
<DebugType>pdbonly</DebugType>
28+
<Optimize>true</Optimize>
29+
<OutputPath>..\..\Output\Release\Plugins\Flow.Launcher.Plugin.ProcessKiller\</OutputPath>
30+
<DefineConstants>TRACE</DefineConstants>
31+
<ErrorReport>prompt</ErrorReport>
32+
<WarningLevel>4</WarningLevel>
33+
<Prefer32Bit>false</Prefer32Bit>
34+
</PropertyGroup>
35+
36+
<ItemGroup>
37+
<Content Include="Images\app.png">
38+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
39+
</Content>
40+
<Content Include="Languages\en.xaml">
41+
<SubType>Designer</SubType>
42+
<Generator>MSBuild:Compile</Generator>
43+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
44+
</Content>
45+
<Content Include="plugin.json">
46+
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
47+
</Content>
48+
</ItemGroup>
49+
50+
<ItemGroup>
51+
<ProjectReference Include="..\..\Flow.Launcher.Infrastructure\Flow.Launcher.Infrastructure.csproj" />
52+
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
53+
</ItemGroup>
54+
55+
</Project>
1.31 KB
Loading
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
2+
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
3+
xmlns:system="clr-namespace:System;assembly=mscorlib">
4+
5+
<system:String x:Key="flowlauncher_plugin_processkiller_plugin_name">Process Killer</system:String>
6+
<system:String x:Key="flowlauncher_plugin_processkiller_plugin_description">Kill running processes from Flow Launcher</system:String>
7+
8+
<system:String x:Key="flowlauncher_plugin_processkiller_kill_all">kill all "{0}" processes</system:String>
9+
<system:String x:Key="flowlauncher_plugin_processkiller_kill_instances">kill all instances</system:String>
10+
11+
</ResourceDictionary>
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Diagnostics;
6+
using System.Dynamic;
7+
using System.Runtime.InteropServices;
8+
using Flow.Launcher.Infrastructure;
9+
using Flow.Launcher.Infrastructure.Logger;
10+
11+
namespace Flow.Launcher.Plugin.ProcessKiller
12+
{
13+
public class Main : IPlugin, IPluginI18n, IContextMenu
14+
{
15+
private ProcessHelper processHelper = new ProcessHelper();
16+
17+
private static PluginInitContext _context;
18+
19+
public void Init(PluginInitContext context)
20+
{
21+
_context = context;
22+
}
23+
24+
public List<Result> Query(Query query)
25+
{
26+
var termToSearch = query.Terms.Length <= 1
27+
? null
28+
: string.Join(Plugin.Query.TermSeperater, query.Terms.Skip(1)).ToLower();
29+
30+
var processlist = processHelper.GetMatchingProcesses(termToSearch);
31+
32+
return !processlist.Any()
33+
? null
34+
: CreateResultsFromProcesses(processlist, termToSearch);
35+
}
36+
37+
public string GetTranslatedPluginTitle()
38+
{
39+
return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_name");
40+
}
41+
42+
public string GetTranslatedPluginDescription()
43+
{
44+
return _context.API.GetTranslation("flowlauncher_plugin_processkiller_plugin_description");
45+
}
46+
47+
public List<Result> LoadContextMenus(Result result)
48+
{
49+
var menuOptions = new List<Result>();
50+
var processPath = result.SubTitle;
51+
52+
// get all non-system processes whose file path matches that of the given result (processPath)
53+
var similarProcesses = processHelper.GetSimilarProcesses(processPath);
54+
55+
menuOptions.Add(new Result
56+
{
57+
Title = _context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_instances"),
58+
SubTitle = processPath,
59+
Action = _ =>
60+
{
61+
foreach (var p in similarProcesses)
62+
{
63+
processHelper.TryKill(p);
64+
}
65+
66+
return true;
67+
},
68+
IcoPath = processPath
69+
});
70+
71+
return menuOptions;
72+
}
73+
74+
private List<Result> CreateResultsFromProcesses(List<ProcessResult> processlist, string termToSearch)
75+
{
76+
var results = new List<Result>();
77+
78+
foreach (var pr in processlist)
79+
{
80+
var p = pr.Process;
81+
var path = processHelper.TryGetProcessFilename(p);
82+
results.Add(new Result()
83+
{
84+
IcoPath = path,
85+
Title = p.ProcessName + " - " + p.Id,
86+
SubTitle = path,
87+
TitleHighlightData = StringMatcher.FuzzySearch(termToSearch, p.ProcessName).MatchData,
88+
Score = pr.Score,
89+
Action = (c) =>
90+
{
91+
processHelper.TryKill(p);
92+
return true;
93+
}
94+
});
95+
}
96+
97+
// When there are multiple results AND all of them are instances of the same executable
98+
// add a quick option to kill them all at the top of the results.
99+
var firstResult = results.FirstOrDefault()?.SubTitle;
100+
if (processlist.Count > 1 && !string.IsNullOrEmpty(termToSearch) && results.All(r => r.SubTitle == firstResult))
101+
{
102+
results.Insert(0, new Result()
103+
{
104+
IcoPath = "Images/app.png",
105+
Title = string.Format(_context.API.GetTranslation("flowlauncher_plugin_processkiller_kill_all"), termToSearch),
106+
SubTitle = "",
107+
Score = 200,
108+
Action = (c) =>
109+
{
110+
foreach (var p in processlist)
111+
{
112+
processHelper.TryKill(p.Process);
113+
}
114+
115+
return true;
116+
}
117+
});
118+
}
119+
120+
return results;
121+
}
122+
}
123+
}
Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
using Flow.Launcher.Infrastructure;
2+
using Flow.Launcher.Infrastructure.Logger;
3+
using System;
4+
using System.Collections.Generic;
5+
using System.Diagnostics;
6+
using System.Linq;
7+
using System.Runtime.InteropServices;
8+
using System.Text;
9+
10+
namespace Flow.Launcher.Plugin.ProcessKiller
11+
{
12+
internal class ProcessHelper
13+
{
14+
private readonly HashSet<string> _systemProcessList = new HashSet<string>()
15+
{
16+
"conhost",
17+
"svchost",
18+
"idle",
19+
"system",
20+
"rundll32",
21+
"csrss",
22+
"lsass",
23+
"lsm",
24+
"smss",
25+
"wininit",
26+
"winlogon",
27+
"services",
28+
"spoolsv",
29+
"explorer"
30+
};
31+
32+
private bool IsSystemProcess(Process p) => _systemProcessList.Contains(p.ProcessName.ToLower());
33+
34+
/// <summary>
35+
/// Returns a ProcessResult for evey running non-system process whose name matches the given searchTerm
36+
/// </summary>
37+
public List<ProcessResult> GetMatchingProcesses(string searchTerm)
38+
{
39+
var processlist = new List<ProcessResult>();
40+
41+
foreach (var p in Process.GetProcesses())
42+
{
43+
if (IsSystemProcess(p)) continue;
44+
45+
if (string.IsNullOrWhiteSpace(searchTerm))
46+
{
47+
// show all non-system processes
48+
processlist.Add(new ProcessResult(p, 0));
49+
}
50+
else
51+
{
52+
var score = StringMatcher.FuzzySearch(searchTerm, p.ProcessName + p.Id).Score;
53+
if (score > 0)
54+
{
55+
processlist.Add(new ProcessResult(p, score));
56+
}
57+
}
58+
}
59+
60+
return processlist;
61+
}
62+
63+
/// <summary>
64+
/// Returns all non-system processes whose file path matches the given processPath
65+
/// </summary>
66+
public IEnumerable<Process> GetSimilarProcesses(string processPath)
67+
{
68+
return Process.GetProcesses().Where(p => !IsSystemProcess(p) && TryGetProcessFilename(p) == processPath);
69+
}
70+
71+
public void TryKill(Process p)
72+
{
73+
try
74+
{
75+
if (!p.HasExited)
76+
{
77+
p.Kill();
78+
}
79+
}
80+
catch (Exception e)
81+
{
82+
Log.Exception($"|ProcessKiller.CreateResultsFromProcesses|Failed to kill process {p.ProcessName}", e);
83+
}
84+
}
85+
86+
public string TryGetProcessFilename(Process p)
87+
{
88+
try
89+
{
90+
int capacity = 2000;
91+
StringBuilder builder = new StringBuilder(capacity);
92+
IntPtr ptr = OpenProcess(ProcessAccessFlags.QueryLimitedInformation, false, p.Id);
93+
if (!QueryFullProcessImageName(ptr, 0, builder, ref capacity))
94+
{
95+
return String.Empty;
96+
}
97+
98+
return builder.ToString();
99+
}
100+
catch
101+
{
102+
return "";
103+
}
104+
}
105+
106+
[Flags]
107+
private enum ProcessAccessFlags : uint
108+
{
109+
QueryLimitedInformation = 0x00001000
110+
}
111+
112+
[DllImport("kernel32.dll", SetLastError = true)]
113+
private static extern bool QueryFullProcessImageName(
114+
[In] IntPtr hProcess,
115+
[In] int dwFlags,
116+
[Out] StringBuilder lpExeName,
117+
ref int lpdwSize);
118+
119+
[DllImport("kernel32.dll", SetLastError = true)]
120+
private static extern IntPtr OpenProcess(
121+
ProcessAccessFlags processAccess,
122+
bool bInheritHandle,
123+
int processId);
124+
}
125+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
using System.Diagnostics;
2+
3+
namespace Flow.Launcher.Plugin.ProcessKiller
4+
{
5+
internal class ProcessResult
6+
{
7+
public ProcessResult(Process process, int score)
8+
{
9+
Process = process;
10+
Score = score;
11+
}
12+
13+
public Process Process { get; }
14+
15+
public int Score { get; }
16+
}
17+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
Process Killer Plugin
2+
=====================
3+
4+
A Flow-Launcher plugin that allows you to kill running processes.
5+
6+
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).
7+
8+
![image](https://user-images.githubusercontent.com/697917/86478286-b4697700-bd52-11ea-875a-b3b90fa34bf2.png)
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
{
2+
"ID":"b64d0a79-329a-48b0-b53f-d658318a1bf6",
3+
"ActionKeyword":"kill",
4+
"Name":"Process Killer",
5+
"Description":"kill running processes from Flow",
6+
"Author":"Flow-Launcher",
7+
"Version":"1.0.0",
8+
"Language":"csharp",
9+
"Website":"https://github.com/Flow-Launcher/Flow.Launcher.Plugin.ProcessKiller",
10+
"IcoPath":"Images\\app.png",
11+
"ExecuteFileName":"Flow.Launcher.Plugin.ProcessKiller.dll"
12+
}

0 commit comments

Comments
 (0)