using System; using System.Diagnostics; using System.IO; using System.Runtime.InteropServices; namespace XP.Common.Helpers { /// /// 进程管理工具类 | Process Management Helper /// 提供启动外部程序、窗口置前等通用功能 | Provides common functions like launching external programs and bringing windows to front /// public static class ProcessHelper { #region Win32 API [DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); [DllImport("user32.dll")] private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); [DllImport("user32.dll")] private static extern bool IsIconic(IntPtr hWnd); private const int SW_RESTORE = 9; #endregion /// /// 启动或激活外部程序 | Start or activate an external program /// /// 可执行文件完整路径 | Full path to the executable /// 是否单实例模式:true=已运行则置前,false=直接启动新实例 | Single instance mode: true=activate if running, false=always start new instance /// 操作结果 | Operation result public static ProcessResult StartOrActivate(string exePath, bool singleInstance = true) { if (string.IsNullOrWhiteSpace(exePath)) { return ProcessResult.Fail("程序路径未配置 | Program path not configured"); } if (!File.Exists(exePath)) { return ProcessResult.Fail($"程序文件不存在: {exePath} | Program file not found: {exePath}"); } try { // 获取进程名(不含扩展名)| Get process name (without extension) var processName = Path.GetFileNameWithoutExtension(exePath); if (singleInstance) { var processes = Process.GetProcessesByName(processName); if (processes.Length > 0) { // 程序已运行,将窗口置前 | Program already running, bring window to front var process = processes[0]; var hWnd = process.MainWindowHandle; if (hWnd != IntPtr.Zero) { BringToFront(hWnd); } return ProcessResult.Activated(); } } // 启动程序 | Start program Process.Start(new ProcessStartInfo { FileName = exePath, UseShellExecute = true }); return ProcessResult.Started(); } catch (Exception ex) { return ProcessResult.Fail($"操作失败: {ex.Message} | Operation failed: {ex.Message}"); } } /// /// 判断指定进程是否正在运行 | Check if a process is running /// /// 进程名(不含扩展名)| Process name (without extension) /// 是否运行中 | Whether the process is running public static bool IsProcessRunning(string processName) { return Process.GetProcessesByName(processName).Length > 0; } /// /// 根据可执行文件路径查找已运行的进程 | Find a running process by executable file path /// 通过进程名匹配并验证完整路径,确保找到的是同一个程序 | Matches by process name and verifies full path /// /// 可执行文件完整路径 | Full path to the executable /// 找到的进程对象,未找到返回 null | The found process, or null if not found public static Process FindRunningProcess(string exePath) { if (string.IsNullOrWhiteSpace(exePath)) return null; var processName = Path.GetFileNameWithoutExtension(exePath); var normalizedTarget = NormalizePath(exePath); try { var processes = Process.GetProcessesByName(processName); foreach (var proc in processes) { try { // 验证完整路径匹配,避免同名不同路径的进程误关联 var procPath = proc.MainModule?.FileName; if (procPath != null && string.Equals(NormalizePath(procPath), normalizedTarget, StringComparison.OrdinalIgnoreCase)) { return proc; } } catch { // 无法访问进程信息(权限不足等),跳过 } } } catch { // GetProcessesByName 异常,返回 null } return null; } /// /// 标准化文件路径,用于路径比较 | Normalize file path for comparison /// private static string NormalizePath(string path) { return Path.GetFullPath(path).TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); } /// /// 将窗口置前显示 | Bring a window to the foreground /// /// 窗口句柄 | Window handle public static void BringToFront(IntPtr hWnd) { if (hWnd == IntPtr.Zero) return; // 如果窗口被最小化,先恢复 | If window is minimized, restore it first if (IsIconic(hWnd)) { ShowWindow(hWnd, SW_RESTORE); } SetForegroundWindow(hWnd); } } /// /// 进程操作结果 | Process Operation Result /// public class ProcessResult { /// /// 是否成功 | Whether the operation succeeded /// public bool Success { get; private set; } /// /// 是否为新启动(false表示激活已有窗口)| Whether it was newly started (false means activated existing window) /// public bool IsNewlyStarted { get; private set; } /// /// 错误信息 | Error message /// public string ErrorMessage { get; private set; } /// /// 创建启动成功结果 | Create a started result /// public static ProcessResult Started() => new() { Success = true, IsNewlyStarted = true }; /// /// 创建激活成功结果 | Create an activated result /// public static ProcessResult Activated() => new() { Success = true, IsNewlyStarted = false }; /// /// 创建失败结果 | Create a failed result /// public static ProcessResult Fail(string errorMessage) => new() { Success = false, ErrorMessage = errorMessage }; } }