diff --git a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs index 6ea107e..4b7f1b2 100644 --- a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs +++ b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/BaseClass/GraphicCardI2CCtrl.cs @@ -144,15 +144,165 @@ namespace WinISP.BaseClass } } + private readonly object _graphicsCardLock = new object(); + private volatile bool _isDisposing = false; + private void FreeGraphicsCardCtrl() { - // Free the GCHandle. - frmISP.WriteLog("Free the GCHandle.", "debug"); - if (gch.IsAllocated) - gch.Free(); - DisposeGraphicCardCtrl(); - pGraphicCardCtrl = IntPtr.Zero; - _IsInit = false; + lock (_graphicsCardLock) + { + // 防止重复释放 + if (_isDisposing) + { + frmISP.WriteLog("Graphics card control is already being disposed, skipping.", "warn"); + return; + } + + if (!_IsInit) + { + frmISP.WriteLog("Graphics card control is not initialized, nothing to free.", "debug"); + return; + } + + _isDisposing = true; + + try + { + // 第一步:释放 GCHandle + FreeGCHandle(); + + // 第二步:释放图形卡控制资源 + DisposeGraphicsCardControl(); + + // 第三步:清空指针 + pGraphicCardCtrl = IntPtr.Zero; + + // 第四步:更新状态 + _IsInit = false; + + frmISP.WriteLog("Graphics card control freed successfully.", "info"); + } + catch (Exception ex) + { + frmISP.WriteLog($"Error freeing graphics card control: {ex.GetType().Name} - {ex.Message}", "error"); + // 即使出错也要尝试清理状态 + try + { + pGraphicCardCtrl = IntPtr.Zero; + _IsInit = false; + } + catch (Exception cleanupEx) + { + frmISP.WriteLog($"Error during cleanup after exception: {cleanupEx.Message}", "error"); + } + } + finally + { + _isDisposing = false; + } + } + } + + /// + /// 安全释放 GCHandle + /// + private void FreeGCHandle() + { + try + { + if (gch.IsAllocated) + { + frmISP.WriteLog("Freeing GCHandle...", "debug"); + gch.Free(); + frmISP.WriteLog("GCHandle freed successfully.", "debug"); + } + else + { + frmISP.WriteLog("GCHandle is not allocated, skipping free operation.", "debug"); + } + } + catch (InvalidOperationException ex) + { + frmISP.WriteLog($"InvalidOperationException when freeing GCHandle: {ex.Message}", "warn"); + } + catch (Exception ex) + { + frmISP.WriteLog($"Unexpected exception when freeing GCHandle: {ex.GetType().Name} - {ex.Message}", "error"); + } + } + + /// + /// 安全释放图形卡控制资源 + /// + private void DisposeGraphicsCardControl() + { + try + { + if (pGraphicCardCtrl != IntPtr.Zero) + { + frmISP.WriteLog("Disposing graphics card control...", "debug"); + DisposeGraphicCardCtrl(); + frmISP.WriteLog("Graphics card control disposed successfully.", "debug"); + } + else + { + frmISP.WriteLog("Graphics card control pointer is null, skipping dispose.", "debug"); + } + } + catch (AccessViolationException ex) + { + frmISP.WriteLog($"AccessViolationException when disposing graphics card control: {ex.Message}", "error"); + } + catch (ObjectDisposedException ex) + { + frmISP.WriteLog($"ObjectDisposedException when disposing graphics card control: {ex.Message}", "warn"); + } + catch (Exception ex) + { + frmISP.WriteLog($"Unexpected exception when disposing graphics card control: {ex.GetType().Name} - {ex.Message}", "error"); + } + } + + /// + /// 验证图形卡控制是否已正确释放 + /// + public bool IsGraphicsCardControlFreed() + { + lock (_graphicsCardLock) + { + return !_IsInit && pGraphicCardCtrl == IntPtr.Zero && !gch.IsAllocated; + } + } + + /// + /// 强制清理(用于异常恢复) + /// + public void ForceCleanupGraphicsCardCtrl() + { + lock (_graphicsCardLock) + { + try + { + frmISP.WriteLog("Performing force cleanup of graphics card control...", "warn"); + + // 强制释放 GCHandle + if (gch.IsAllocated) + { + try { gch.Free(); } + catch { } + } + + // 强制清空指针 + pGraphicCardCtrl = IntPtr.Zero; + _IsInit = false; + + frmISP.WriteLog("Force cleanup completed.", "info"); + } + catch (Exception ex) + { + frmISP.WriteLog($"Error during force cleanup: {ex.Message}", "error"); + } + } } public GraphicCardI2CCtrl() diff --git a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs index fec742c..768a467 100644 --- a/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs +++ b/WIN10_WinISP_SrcCode_For_MOKA_20250416_1/WinISP/FormISP_MSI.cs @@ -125,15 +125,125 @@ namespace WinISP public void CheckSingleInstance() { - Process[] thisnameprocesslist; - string modulename, processname; - Process p = Process.GetCurrentProcess(); - modulename = p.MainModule.ModuleName.ToString(); - processname = System.IO.Path.GetFileNameWithoutExtension(modulename); - thisnameprocesslist = Process.GetProcessesByName(processname); - if (thisnameprocesslist.Length > 1) + Process currentProcess = null; + Process[] processList = null; + + try { - Application.Exit(); + currentProcess = Process.GetCurrentProcess(); + + // 安全获取模块名称 + if (currentProcess.MainModule == null) + { + frmISP.WriteLog("Failed to get MainModule, cannot perform single instance check", "error"); + return; + } + + string moduleName = currentProcess.MainModule.ModuleName; + string processName = System.IO.Path.GetFileNameWithoutExtension(moduleName); + + frmISP.WriteLog($"Current process name: {processName}, PID: {currentProcess.Id}", "debug"); + + // 获取同名进程列表 + processList = Process.GetProcessesByName(processName); + + frmISP.WriteLog($"Found {processList.Length} process(es) with name '{processName}'", "debug"); + + // 检查是否存在多个实例 + if (processList.Length > 1) + { + frmISP.WriteLog($"Multiple instances detected ({processList.Length}). Exiting application.", "warn"); + + // 可选:激活已存在的实例窗口 + ActivateExistingInstance(processList, currentProcess.Id); + + Application.Exit(); + } + else + { + frmISP.WriteLog("Single instance check passed. Application is running as the only instance.", "debug"); + } + } + catch (System.ComponentModel.Win32Exception ex) + { + frmISP.WriteLog($"Win32Exception in CheckSingleInstance: {ex.Message}", "error"); + } + catch (UnauthorizedAccessException ex) + { + frmISP.WriteLog($"UnauthorizedAccessException in CheckSingleInstance: {ex.Message}", "error"); + } + catch (Exception ex) + { + frmISP.WriteLog($"Unexpected exception in CheckSingleInstance: {ex.GetType().Name} - {ex.Message}", "error"); + } + finally + { + // 释放 Process 资源 + if (processList != null) + { + foreach (var p in processList) + { + p?.Dispose(); + } + } + currentProcess?.Dispose(); + } + } + + /// + /// 尝试激活已存在的应用实例窗口 + /// + private void ActivateExistingInstance(Process[] processList, int currentPid) + { + try + { + foreach (var process in processList) + { + // 跳过当前进程 + if (process.Id == currentPid) + continue; + + // 尝试获取主窗口句柄 + if (process.MainWindowHandle != IntPtr.Zero) + { + // 恢复窗口(如果最小化) + if (IsWindowMinimized(process.MainWindowHandle)) + { + ShowWindow(process.MainWindowHandle, 9); // SW_RESTORE + } + + // 激活窗口 + SetForegroundWindow(process.MainWindowHandle); + frmISP.WriteLog($"Activated existing instance (PID: {process.Id})", "info"); + return; + } + } + } + catch (Exception ex) + { + frmISP.WriteLog($"Failed to activate existing instance: {ex.Message}", "warn"); + } + } + + // Windows API 声明 + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool SetForegroundWindow(IntPtr hWnd); + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow); + + [System.Runtime.InteropServices.DllImport("user32.dll")] + private static extern bool IsIconic(IntPtr hWnd); + + private bool IsWindowMinimized(IntPtr hWnd) + { + try + { + return IsIconic(hWnd); + } + catch + { + return false; } }