如何防止表单再次打开?

3

如何防止表单再次打开。我制作了我的应用程序并安装了它,但是当我再次点击图标时,应用程序会再次打开,如果我再次点击图标,应用程序将继续打开,如何防止这种情况发生?


1
需要考虑的是,这往往会任意限制您的用户。 - Chris Marisic
4个回答

5

Scott Hanselman之前写了一篇关于这个问题的好文章 - 这是链接


在所有发布到这个问题的解决方案中,如果你正在使用.NET,那么这个是正确的。它不涉及使用互斥体或终止进程,并利用内置功能,提供对已经运行的实例需要执行的操作的完全控制。选择这个吧。+1 - Umar Farooq Khawaja

2

尝试使用Mutex。这是一篇关于此主题的好文章:

http://odetocode.com/Blogs/scott/archive/2004/08/20/401.aspx

[STAThread]
static void Main() 
{
   using(Mutex mutex = new Mutex(false, "Global\\" + appGuid))
   {
      if(!mutex.WaitOne(0, false))
      {
         MessageBox.Show("Instance already running");
         return;
      }

      Application.Run(new Form1());
   }
}

你为什么在这里使用 GC.Collection() - Jalal Said
该文章解释了GC.Collection()的作用是证明这段代码没有问题(使用它可以通过垃圾回收器保持Mutex的存活状态)-- 因此,垃圾回收操作可以被移除。 - Lou Franco
@Lou 我明白了,他只是从文章中复制和粘贴了代码内容,甚至没有对其进行诊断。 - Jalal Said

1

您可以通过检查当前运行的进程列表来实现。 如果是重复的,请自我终止。 这将防止多个实例。

   Process[] pArry = Process.GetProcesses();   //Get Currently Running Processes   
   int Instance_Counter = 0; // To count No. of Instances

  foreach (Process p in pArry) 
       {         
          string ProcessName = p.ProcessName;   
        //Match the Process Name with Current Process (i.e. Check Duplication )
       //If So Kill self
        if(ProcessName == Process.GetCurrentProcess().ProcessName)                
         {              
            Instance_Counter++;   
        }    
           } 

    if(Instance_Counter>1)
    {
       //Show Error and Kill Yourself
    }

这段代码的问题在于,可能会在if检查成功后立即终止第一个应用程序实例,因此最终你将没有任何应用程序实例在运行。 - Jalal Said
同样的问题仍然存在,因为在执行 if (Instance_Counter>1) 后它可能会被关闭。 - Jalal Said
@Jalal Aldeen Saa'd:这是预期的结果,对吗?如果用户打开了另一个实例,则显示错误消息,例如“应用程序已在运行中”,并防止用户打开另一个窗口! - Swanand
不,这里存在竞态条件。也就是说,在foreach语句执行完毕并发现有一个正在运行的实例"Instance_Counter > 1"之后,由于代码正在执行时已经发现运行的实例可能会被终止,因此用户试图运行新实例可能会失败! --> - Jalal Said
--> 因此,您最终会显示错误消息,并且没有实例正在运行。"旧实例刚刚终止,新实例无法启动,因为在代码执行时发现了一个正在运行的实例,但是该实例在执行代码之前已经终止。这是一种竞争条件,使用Mutex将结束它。希望您现在明白了。 - Jalal Said

0

这不是最好的方法,但是 Swanand Purankar 提到的固定方法:

//I set Timer's interval to "250", it's personal
//Just don't forget to enable the timer
private void timer1_Tick(object sender, EventArgs e)
{
    var self = Process.GetCurrentProcess();
    foreach (var proc in Process.GetProcessesByName(self.ProcessName))
    {
        if (proc.Id != self.Id)
        {
            proc.Kill();
        }
    }
}

但是使用这种方式,您无法设置错误。如果您想要设置错误:

private void Form1_Load(object sender, EventArgs e)
{
    if (Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName).Length > 1)
    {
        MessageBox.Show("Hey there opening multiple instances of this process is restricted!", "Error",
            MessageBoxButtons.OK, MessageBoxIcon.Error);
        this.Close();
    }
}

然而,用户可以通过重命名程序轻松地绕过此问题。使用注册表可以帮助解决这个问题。但黑客/开发人员仍然可以通过使用进程监视器来摆脱这个问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接