增加日志,完善逻辑
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全释放 GCHandle
|
||||
/// </summary>
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安全释放图形卡控制资源
|
||||
/// </summary>
|
||||
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");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 验证图形卡控制是否已正确释放
|
||||
/// </summary>
|
||||
public bool IsGraphicsCardControlFreed()
|
||||
{
|
||||
lock (_graphicsCardLock)
|
||||
{
|
||||
return !_IsInit && pGraphicCardCtrl == IntPtr.Zero && !gch.IsAllocated;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 强制清理(用于异常恢复)
|
||||
/// </summary>
|
||||
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()
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 尝试激活已存在的应用实例窗口
|
||||
/// </summary>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user