【问题标题】:Restrict multiple instances of an application限制应用程序的多个实例
【发布时间】:2026-01-12 02:55:02
【问题描述】:

好的,所以我已经创建了我的 c# 应用程序,为它创建了一个安装程序,并将它安装在我的机器上。

问题是,当用户打开应用程序exe两次时,会有两个应用程序实例在运行。我只希望应用程序的一个实例在任何时候都运行,我该怎么做?

感谢您的帮助,

【问题讨论】:

    标签: c# .net c#-2.0 multiple-instances


    【解决方案1】:

    对此的常用技术是创建一个名为Mutex 并在应用程序启动时检查它的存在。

    请参阅thisthis

    来自 DDJ 的代码:

    class App : Form
    {
        Mutex mutex;
    
        App()
        {
            Text = "Single Instance!";
            mutex = new Mutex(false, "SINGLE_INSTANCE_MUTEX");
            if (!mutex.WaitOne(0, false)) 
            {
                mutex.Close();
                mutex = null;
            }
        }
    
        protected override void Dispose(bool disposing)
        {
            if (disposing)
                mutex.ReleaseMutex();
            base.Dispose(disposing);
        }
    
        static void Main()
        {
            App app = new App();
            if (app.mutex != null) Application.Run(app);
            else MessageBox.Show("Instance already running");
        }
    }
    

    【讨论】:

    • 请在答案中显示代码。第一个链接已失效,其他链接最终可能会效仿。
    【解决方案2】:

    我不知道您在其中运行的环境,但是关于“单实例应用程序”要记住的一点是您如何定义单实例。如果应用程序可以同时在多个工作站上运行,使用一个公共数据源,这是一个问题吗?同样,如果有多个用户登录到同一台计算机的终端服务情况(或“运行方式”情况),您是否希望以这样一种方式限制应用程序,即每个用户只有一个实例,每个-计算机?或者您可以接受它只是每个用户一个实例吗?

    这些问题的答案可能会引导您走向一个方向而不是另一个方向。例如,我们有一个“单实例”应用程序,其范围是一组计算机。该组工作站中只允许一个用户使用。我们通过在我们的共享数据源中有一个表来跟踪当前连接的用户来管理它。这是一个维护问题,因为您需要确保该表始终 100% 准确。处理工作站上的意外断电等问题,在该表中留下“虚假”记录需要一些小心处理。

    【讨论】:

      【解决方案3】:

      感谢Messrs.AllenPowell

      static void Main() 
      {
          using (Mutex mutex = new Mutex(false, @"Global\" + appGuid)) {
              if (!mutex.WaitOne(0, false)) {
                  string processName = GetProcessName();
                  BringOldInstanceToFront(processName);
              }
              else {
                  GC.Collect();
                  Application.Run(new Voting());
              }
          }
      }
      
      private static void BringOldInstanceToFront(string processName) {
          Process[] RunningProcesses = Process.GetProcessesByName(processName);
          if (RunningProcesses.Length > 0) {
              Process runningProcess = RunningProcesses[0];
              if (runningProcess != null) {
                  IntPtr mainWindowHandle = runningProcess.MainWindowHandle;
                  NativeMethods.ShowWindowAsync(mainWindowHandle, (int) WindowConstants.ShowWindowConstants.SW_SHOWMINIMIZED);
              NativeMethods.ShowWindowAsync(mainWindowHandle, (int) WindowConstants.ShowWindowConstants.SW_RESTORE);
              }
          }
      }
      

      【讨论】:

        【解决方案4】:

        我通过这个解决了这个问题

        [STAThread]
         static void Main()
            {
        
                Process[] result = Process.GetProcessesByName("ApplicationName");
                if (result.Length > 1)
                {
                    MessageBox.Show("There is already a instance running.", "Information");
                    System.Environment.Exit(0);
                }
                // here normal start 
            }
        

        这很简单,但我几乎没有时间检查更好的解决方案。

        【讨论】:

        • 如果有人以不同的名称获取应用程序的副本并作为新进程启动,则会有多个实例。因此,请使用 processObject.MainModule.FileInfo 字段,例如描述或原始文件名.. 即使重命名可执行文件也不会更改