feat: add csharp win helper probe
This commit is contained in:
172
native/ISphereWinHelper/WindowScanner.cs
Normal file
172
native/ISphereWinHelper/WindowScanner.cs
Normal file
@@ -0,0 +1,172 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace ISphereWinHelper
|
||||
{
|
||||
internal static class WindowScanner
|
||||
{
|
||||
private delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool IsWindowVisible(IntPtr hWnd);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);
|
||||
|
||||
[DllImport("user32.dll", SetLastError = true)]
|
||||
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
||||
|
||||
[DllImport("user32.dll")]
|
||||
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
|
||||
|
||||
[StructLayout(LayoutKind.Sequential)]
|
||||
private struct RECT
|
||||
{
|
||||
public int Left;
|
||||
public int Top;
|
||||
public int Right;
|
||||
public int Bottom;
|
||||
}
|
||||
|
||||
public static Dictionary<string, object> Scan(Dictionary<string, object> args)
|
||||
{
|
||||
bool includeAllVisible = HelperProtocol.GetBool(args, "include_all_visible", false);
|
||||
var windows = new List<Dictionary<string, object>>();
|
||||
|
||||
EnumWindows(delegate(IntPtr hwnd, IntPtr lParam)
|
||||
{
|
||||
if (!IsWindowVisible(hwnd))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
string title = GetWindowTextValue(hwnd);
|
||||
string className = GetClassNameValue(hwnd);
|
||||
uint pidRaw;
|
||||
GetWindowThreadProcessId(hwnd, out pidRaw);
|
||||
int pid = unchecked((int)pidRaw);
|
||||
string processName = GetProcessName(pid);
|
||||
int score = ScoreWindow(processName, title, className);
|
||||
|
||||
if (!includeAllVisible && score <= 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
RECT rect;
|
||||
GetWindowRect(hwnd, out rect);
|
||||
windows.Add(new Dictionary<string, object>
|
||||
{
|
||||
{ "hwnd", FormatHwnd(hwnd) },
|
||||
{ "pid", pid },
|
||||
{ "process_name", processName },
|
||||
{ "title", title },
|
||||
{ "class_name", className },
|
||||
{ "visible", true },
|
||||
{ "bounds", new Dictionary<string, object>
|
||||
{
|
||||
{ "x", rect.Left },
|
||||
{ "y", rect.Top },
|
||||
{ "width", Math.Max(0, rect.Right - rect.Left) },
|
||||
{ "height", Math.Max(0, rect.Bottom - rect.Top) }
|
||||
}
|
||||
},
|
||||
{ "score", score }
|
||||
});
|
||||
|
||||
return true;
|
||||
}, IntPtr.Zero);
|
||||
|
||||
windows.Sort(delegate(Dictionary<string, object> left, Dictionary<string, object> right)
|
||||
{
|
||||
return Convert.ToInt32(right["score"]).CompareTo(Convert.ToInt32(left["score"]));
|
||||
});
|
||||
|
||||
return new Dictionary<string, object> { { "windows", windows } };
|
||||
}
|
||||
|
||||
public static bool TryParseHwnd(string text, out IntPtr hwnd)
|
||||
{
|
||||
hwnd = IntPtr.Zero;
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
string normalized = text.Trim();
|
||||
try
|
||||
{
|
||||
long value;
|
||||
if (normalized.StartsWith("0x", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
value = Convert.ToInt64(normalized.Substring(2), 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = Convert.ToInt64(normalized, 10);
|
||||
}
|
||||
hwnd = new IntPtr(value);
|
||||
return hwnd != IntPtr.Zero;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public static string FormatHwnd(IntPtr hwnd)
|
||||
{
|
||||
return "0x" + hwnd.ToInt64().ToString("X");
|
||||
}
|
||||
|
||||
private static string GetWindowTextValue(IntPtr hwnd)
|
||||
{
|
||||
var buffer = new StringBuilder(512);
|
||||
GetWindowText(hwnd, buffer, buffer.Capacity);
|
||||
return buffer.ToString();
|
||||
}
|
||||
|
||||
private static string GetClassNameValue(IntPtr hwnd)
|
||||
{
|
||||
var buffer = new StringBuilder(256);
|
||||
GetClassName(hwnd, buffer, buffer.Capacity);
|
||||
return buffer.ToString();
|
||||
}
|
||||
|
||||
private static string GetProcessName(int pid)
|
||||
{
|
||||
try
|
||||
{
|
||||
using (Process process = Process.GetProcessById(pid))
|
||||
{
|
||||
return process.ProcessName;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private static int ScoreWindow(string processName, string title, string className)
|
||||
{
|
||||
int score = 0;
|
||||
string combined = ((processName ?? "") + " " + (title ?? "") + " " + (className ?? "")).ToLowerInvariant();
|
||||
if (combined.Contains("implatformclient")) score += 60;
|
||||
if (combined.Contains("isphere")) score += 50;
|
||||
if (combined.Contains("impp")) score += 30;
|
||||
if (combined.Contains("importal")) score += 20;
|
||||
if ((className ?? "").IndexOf("WindowsForms", StringComparison.OrdinalIgnoreCase) >= 0) score += 5;
|
||||
return score;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user