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 Scan(Dictionary args) { bool includeAllVisible = HelperProtocol.GetBool(args, "include_all_visible", false); var windows = new List>(); 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 { { "hwnd", FormatHwnd(hwnd) }, { "pid", pid }, { "process_name", processName }, { "title", title }, { "class_name", className }, { "visible", true }, { "bounds", new Dictionary { { "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 left, Dictionary right) { return Convert.ToInt32(right["score"]).CompareTo(Convert.ToInt32(left["score"])); }); return new Dictionary { { "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; } } }