Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions Flow.Launcher.Infrastructure/FileExplorerHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,6 @@ private static dynamic GetActiveExplorer()
return explorerWindows.Zip(zOrders).MinBy(x => x.Second).First;
}

private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

/// <summary>
/// Gets the z-order for one or more windows atomically with respect to each other. In Windows, smaller z-order is higher. If the window is not top level, the z order is returned as -1.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@

using Flow.Launcher.Plugin.PluginsManager.ViewModels;
using Flow.Launcher.Plugin.PluginsManager.ViewModels;

namespace Flow.Launcher.Plugin.PluginsManager.Views
{
Expand All @@ -8,15 +7,11 @@ namespace Flow.Launcher.Plugin.PluginsManager.Views
/// </summary>
public partial class PluginsManagerSettings
{
private readonly SettingsViewModel viewModel;

internal PluginsManagerSettings(SettingsViewModel viewModel)
{
InitializeComponent();

this.viewModel = viewModel;

this.DataContext = viewModel;
DataContext = viewModel;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
<AppendRuntimeIdentifierToOutputPath>false</AppendRuntimeIdentifierToOutputPath>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<UseWPF>true</UseWPF>
</PropertyGroup>

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
Expand Down Expand Up @@ -58,7 +59,6 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Flow.Launcher.Infrastructure\Flow.Launcher.Infrastructure.csproj" />
<ProjectReference Include="..\..\Flow.Launcher.Plugin\Flow.Launcher.Plugin.csproj" />
</ItemGroup>

Expand Down
9 changes: 6 additions & 3 deletions Plugins/Flow.Launcher.Plugin.ProcessKiller/Languages/en.xaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:system="clr-namespace:System;assembly=mscorlib">

<system:String x:Key="flowlauncher_plugin_processkiller_plugin_name">Process Killer</system:String>
<system:String x:Key="flowlauncher_plugin_processkiller_plugin_description">Kill running processes from Flow Launcher</system:String>
Expand All @@ -9,4 +10,6 @@
<system:String x:Key="flowlauncher_plugin_processkiller_kill_all_count">kill {0} processes</system:String>
<system:String x:Key="flowlauncher_plugin_processkiller_kill_instances">kill all instances</system:String>

<system:String x:Key="flowlauncher_plugin_processkiller_put_visible_window_process_top">Put processes with visible windows on the top</system:String>

</ResourceDictionary>
110 changes: 90 additions & 20 deletions Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,27 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Flow.Launcher.Infrastructure;
using System.Windows.Controls;
using Flow.Launcher.Plugin.ProcessKiller.ViewModels;
using Flow.Launcher.Plugin.ProcessKiller.Views;

namespace Flow.Launcher.Plugin.ProcessKiller
{
public class Main : IPlugin, IPluginI18n, IContextMenu
public class Main : IPlugin, IPluginI18n, IContextMenu, ISettingProvider
{
private ProcessHelper processHelper = new ProcessHelper();
private readonly ProcessHelper processHelper = new();

private static PluginInitContext _context;

internal Settings Settings;

private SettingsViewModel _viewModel;

public void Init(PluginInitContext context)
{
_context = context;
Settings = context.API.LoadSettingJsonStorage<Settings>();
_viewModel = new SettingsViewModel(Settings);
}

public List<Result> Query(Query query)
Expand Down Expand Up @@ -48,7 +57,7 @@ public List<Result> LoadContextMenus(Result result)
{
foreach (var p in similarProcesses)
{
processHelper.TryKill(p);
processHelper.TryKill(_context, p);
}

return true;
Expand All @@ -62,45 +71,102 @@ public List<Result> LoadContextMenus(Result result)

private List<Result> CreateResultsFromQuery(Query query)
{
string termToSearch = query.Search;
var processlist = processHelper.GetMatchingProcesses(termToSearch);

if (!processlist.Any())
// Get all non-system processes
var allPocessList = processHelper.GetMatchingProcesses();
if (!allPocessList.Any())
{
return null;
}

var results = new List<Result>();
// Filter processes based on search term
var searchTerm = query.Search;
var processlist = new List<ProcessResult>();
var processWindowTitle = ProcessHelper.GetProcessesWithNonEmptyWindowTitle();
if (string.IsNullOrWhiteSpace(searchTerm))
{
foreach (var p in allPocessList)
{
var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p);

if (processWindowTitle.TryGetValue(p.Id, out var windowTitle))
{
// Add score to prioritize processes with visible windows
// And use window title for those processes
processlist.Add(new ProcessResult(p, Settings.PutVisibleWindowProcessesTop ? 200 : 0, windowTitle, null, progressNameIdTitle));
}
else
{
processlist.Add(new ProcessResult(p, 0, progressNameIdTitle, null, progressNameIdTitle));
}
}
}
else
{
foreach (var p in allPocessList)
{
var progressNameIdTitle = ProcessHelper.GetProcessNameIdTitle(p);

if (processWindowTitle.TryGetValue(p.Id, out var windowTitle))
{
// Get max score from searching process name, window title and process id
var windowTitleMatch = _context.API.FuzzySearch(searchTerm, windowTitle);
var processNameIdMatch = _context.API.FuzzySearch(searchTerm, progressNameIdTitle);
var score = Math.Max(windowTitleMatch.Score, processNameIdMatch.Score);
if (score > 0)
{
// Add score to prioritize processes with visible windows
// And use window title for those processes
if (Settings.PutVisibleWindowProcessesTop)
{
score += 200;
}
processlist.Add(new ProcessResult(p, score, windowTitle,
score == windowTitleMatch.Score ? windowTitleMatch : null, progressNameIdTitle));
}
}
else
{
var processNameIdMatch = _context.API.FuzzySearch(searchTerm, progressNameIdTitle);
var score = processNameIdMatch.Score;
if (score > 0)
{
processlist.Add(new ProcessResult(p, score, progressNameIdTitle, processNameIdMatch, progressNameIdTitle));
}
}
}
}

var results = new List<Result>();
foreach (var pr in processlist)
{
var p = pr.Process;
var path = processHelper.TryGetProcessFilename(p);
results.Add(new Result()
{
IcoPath = path,
Title = p.ProcessName + " - " + p.Id,
Title = pr.Title,
TitleToolTip = pr.Tooltip,
SubTitle = path,
TitleHighlightData = StringMatcher.FuzzySearch(termToSearch, p.ProcessName).MatchData,
TitleHighlightData = pr.TitleMatch?.MatchData,
Score = pr.Score,
ContextData = p.ProcessName,
AutoCompleteText = $"{_context.CurrentPluginMetadata.ActionKeyword}{Plugin.Query.TermSeparator}{p.ProcessName}",
Action = (c) =>
{
processHelper.TryKill(p);
// Re-query to refresh process list
_context.API.ChangeQuery(query.RawQuery, true);
return true;
processHelper.TryKill(_context, p);
_context.API.ReQuery();
return false;
}
});
}

// Order results by process name for processes without visible windows
var sortedResults = results.OrderBy(x => x.Title).ToList();

// 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 = sortedResults.FirstOrDefault(x => !string.IsNullOrEmpty(x.SubTitle));
if (processlist.Count > 1 && !string.IsNullOrEmpty(termToSearch) && sortedResults.All(r => r.SubTitle == firstResult?.SubTitle))
if (processlist.Count > 1 && !string.IsNullOrEmpty(searchTerm) && sortedResults.All(r => r.SubTitle == firstResult?.SubTitle))
{
sortedResults.Insert(1, new Result()
{
Expand All @@ -112,16 +178,20 @@ private List<Result> CreateResultsFromQuery(Query query)
{
foreach (var p in processlist)
{
processHelper.TryKill(p.Process);
processHelper.TryKill(_context, p.Process);
}
// Re-query to refresh process list
_context.API.ChangeQuery(query.RawQuery, true);
return true;
_context.API.ReQuery();
return false;
}
});
}

return sortedResults;
}

public Control CreateSettingPanel()
{
return new SettingsControl(_viewModel);
}
}
}
7 changes: 6 additions & 1 deletion Plugins/Flow.Launcher.Plugin.ProcessKiller/NativeMethods.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
QueryFullProcessImageName
OpenProcess
OpenProcess
EnumWindows
GetWindowTextLength
GetWindowText
IsWindowVisible
GetWindowThreadProcessId
Loading
Loading