防止.NET应用多实例运行的有效方法

ASP.NET教程 2025-08-26

目录

  • 核心思路
  • 代码解析
    • 1、检查是否已有程序运行
    • 2、主程序入口
    • 3、Win32 API 调用
  • 注意事项
    • 优化建议
  • 总结
    • 最后

      核心思路

      1、检查是否已有程序实例运行

      使用 System.Diagnostics.Process获取当前程序进程,并与系统中所有同名的程序进程进行比较。如果发现另一个同名进程,则认为程序已经运行。

      2、激活已运行的程序窗口

      如果发现已有实例运行,使用 Win32 API操作将其窗口置于前台,避免用户启动多个实例。

      3、运行主程序逻辑

      如果没有其他实例运行,正常启动主程序。

      代码解析

      1、检查是否已有程序运行

      以下代码通过进程名称筛选当前运行的程序进程列表,返回除当前进程外的其他同名进程(如果存在):

      public static Process GetExistProcess()  
      {  
          Process currentProcess = Process.GetCurrentProcess(); // 当前程序  
          foreach (Process process in Process.GetProcessesByName(currentProcess.ProcessName))  
          {  
              if (process.Id != currentProcess.Id) // 找到其他同名进程  
              {  
                  return process; // 返回已运行的进程  
              }  
          }  
          return null; // 没有其他实例  
      }  
      

      2、主程序入口

      在Main方法中调用GetExistProcess检查程序实例:

      static class Program  
      {  
          [STAThread]  
          static void Main()  
          {  
              Application.EnableVisualStyles();  
              Application.SetCompatibleTextRenderingDefault(false);  
      
              var runningProcess = GetExistProcess();  
              if (runningProcess != null) // 如果有实例运行  
              {  
                  IntPtr mainWindowHandle = runningProcess.MainWindowHandle;  
                  if (mainWindowHandle == IntPtr.Zero) // 窗口被隐藏  
                  {  
                      mainWindowHandle = FindWindow(null, "唯一程序");  
                  }  
                  ShowWindowAsync(mainWindowHandle, 1); // 显示窗口  
                  SetForegroundWindow(mainWindowHandle); // 置于前台  
              }  
              else  
              {  
                  Application.Run(new MainForm()); // 启动新实例  
              }  
          }  
      }  
      

      3、Win32 API 调用

      以下是关键的Win32 API函数,用于操作窗口显示和前台设置:

      [DllImport("User32.dll", EntryPoint = "FindWindow")]  
      public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);  
      
      [DllImport("user32.dll")]  
      public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);  
      
      [DllImport("user32.dll ")]  
      public static extern bool SetForegroundWindow(IntPtr hWnd);  
      

      FindWindow: 根据窗口名称查找窗口句柄。

      ShowWindowAsync: 显示或隐藏窗口。

      SetForegroundWindow: 将窗口设置为前台窗口。

      注意事项

      1、窗口名称匹配问题

      如果窗口标题动态变化,FindWindow的效果可能不佳,需保证窗口标题唯一或改用其他识别方法。 2、权限问题

      如果以管理员权限运行程序,SetForegroundWindow操作可能会被限制。需要确保权限一致。

      3、多线程问题

      如果程序使用了多线程,需注意线程间的窗口操作同步。

      优化建议

      1、使用互斥量

      利用 Mutex可以更简洁地实现程序唯一性。例如:

      static Mutex mutex = new Mutex(true, "UniqueAppName", out bool createdNew);  
          if (!createdNew)  
          {  
          // 已经有实例运行  
          return;  
          }  
      

      2、窗口句柄缓存

      可以在程序启动时缓存主窗口句柄,避免频繁调用 FindWindow。

      3、日志记录

      在实际应用中建议记录重复启动的尝试,以便后续调试和优化。

      总结

      这是一种基于进程和 Win32 API 的方法来保持程序唯一性的解决方案。代码逻辑清晰,适用于大多数桌面应用场景。如果你有更复杂的需求或更高的性能要求,建议结合互斥量或现代框架特性来实现更可靠的方案。

      最后

      到此这篇关于防止.NET应用多实例运行的有效方法的文章就介绍到这了,更多相关防止.NET多实例运行内容请搜索本站以前的文章或继续浏览下面的相关文章希望大家以后多多支持本站!

      您可能感兴趣的文章:
      • ASP.NETCoreMVC过滤器运行流程解析
      • C#如何判断.Net Framework版本是否满足软件运行需要的版本
      • .NET Core Web APi类库内嵌运行的方法
      • .NET 实现启动时重定向程序运行路径及 Windows 服务运行模式部署的方法
      • .NET项目在k8s中运行的Dapr持续集成流程