Skip to content

Commit fa46513

Browse files
committed
Use PInvoke to replace DllImport
1 parent db5bc41 commit fa46513

File tree

3 files changed

+36
-27
lines changed

3 files changed

+36
-27
lines changed

Plugins/Flow.Launcher.Plugin.ProcessKiller/Main.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller
66
{
77
public class Main : IPlugin, IPluginI18n, IContextMenu
88
{
9-
private ProcessHelper processHelper = new ProcessHelper();
9+
private readonly ProcessHelper processHelper = new();
1010

1111
private static PluginInitContext _context;
1212

@@ -66,7 +66,7 @@ private List<Result> CreateResultsFromQuery(Query query)
6666
{
6767
string termToSearch = query.Search;
6868
var processList = processHelper.GetMatchingProcesses(termToSearch);
69-
var processWithNonEmptyMainWindowTitleList = processHelper.GetProcessesWithNonEmptyWindowTitle();
69+
var processWithNonEmptyMainWindowTitleList = ProcessHelper.GetProcessesWithNonEmptyWindowTitle();
7070

7171
if (!processList.Any())
7272
{
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
QueryFullProcessImageName
2-
OpenProcess
2+
OpenProcess
3+
EnumWindows
4+
GetWindowTextLength
5+
GetWindowText
6+
IsWindowVisible
7+
GetWindowThreadProcessId

Plugins/Flow.Launcher.Plugin.ProcessKiller/ProcessHelper.cs

Lines changed: 28 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,7 @@ namespace Flow.Launcher.Plugin.ProcessKiller
1313
{
1414
internal class ProcessHelper
1515
{
16-
[DllImport("user32.dll")]
17-
private static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);
18-
19-
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
20-
21-
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
22-
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
23-
24-
[DllImport("user32.dll")]
25-
private static extern bool IsWindowVisible(IntPtr hWnd);
26-
27-
[DllImport("user32.dll")]
28-
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
29-
30-
private readonly HashSet<string> _systemProcessList = new HashSet<string>()
16+
private readonly HashSet<string> _systemProcessList = new()
3117
{
3218
"conhost",
3319
"svchost",
@@ -79,22 +65,25 @@ public List<ProcessResult> GetMatchingProcesses(string searchTerm)
7965
/// <summary>
8066
/// Returns a dictionary of process IDs and their window titles for processes that have a visible main window with a non-empty title.
8167
/// </summary>
82-
public Dictionary<int, string> GetProcessesWithNonEmptyWindowTitle()
68+
public static unsafe Dictionary<int, string> GetProcessesWithNonEmptyWindowTitle()
8369
{
8470
var processDict = new Dictionary<int, string>();
85-
EnumWindows((hWnd, lParam) =>
71+
PInvoke.EnumWindows((hWnd, lParam) =>
8672
{
87-
StringBuilder windowTitle = new StringBuilder();
88-
GetWindowText(hWnd, windowTitle, windowTitle.Capacity);
89-
90-
if (!string.IsNullOrWhiteSpace(windowTitle.ToString()) && IsWindowVisible(hWnd))
73+
var windowTitle = GetWindowTitle(hWnd);
74+
if (!string.IsNullOrWhiteSpace(windowTitle) && PInvoke.IsWindowVisible(hWnd))
9175
{
92-
GetWindowThreadProcessId(hWnd, out var processId);
93-
var process = Process.GetProcessById((int)processId);
76+
uint processId = 0;
77+
var result = PInvoke.GetWindowThreadProcessId(hWnd, &processId);
78+
if (result == 0u || processId == 0u)
79+
{
80+
return false;
81+
}
9482

83+
var process = Process.GetProcessById((int)processId);
9584
if (!processDict.ContainsKey((int)processId))
9685
{
97-
processDict.Add((int)processId, windowTitle.ToString());
86+
processDict.Add((int)processId, windowTitle);
9887
}
9988
}
10089

@@ -104,6 +93,21 @@ public Dictionary<int, string> GetProcessesWithNonEmptyWindowTitle()
10493
return processDict;
10594
}
10695

96+
private static unsafe string GetWindowTitle(HWND hwnd)
97+
{
98+
var capacity = PInvoke.GetWindowTextLength(hwnd) + 1;
99+
int length;
100+
Span<char> buffer = capacity < 1024 ? stackalloc char[capacity] : new char[capacity];
101+
fixed (char* pBuffer = buffer)
102+
{
103+
// If the window has no title bar or text, if the title bar is empty,
104+
// or if the window or control handle is invalid, the return value is zero.
105+
length = PInvoke.GetWindowText(hwnd, pBuffer, capacity);
106+
}
107+
108+
return buffer[..length].ToString();
109+
}
110+
107111
/// <summary>
108112
/// Returns all non-system processes whose file path matches the given processPath
109113
/// </summary>

0 commit comments

Comments
 (0)