【问题标题】:How to make sure that there is one instance of the application is running如何确保有一个应用程序实例正在运行
【发布时间】:2010-09-28 07:50:37
【问题描述】:

我想检查用户双击应用程序图标时该应用程序的其他实例是否已在运行。

我阅读了有关 My.Application 的信息,但我仍然不知道该怎么做。

【问题讨论】:

  • 您可能应该指定一种语言、框架和/或操作系统。
  • 我已将此标记为 VB.Net,因为 My.Application 是 VB.Net 功能
  • 添加了单例标签,因为这似乎是必需的。
  • Singleton 在一个应用程序实例中管理单个类实例。你需要一些 CLR / 系统范围的东西,比如互斥锁

标签: vb.net single-instance


【解决方案1】:

这是我用过的东西...(.NET 2.0 上的 C#)

    [STAThread]
    private static void Main(string[] args)
    {
        //this follows best practices on
        //ensuring that this is a single instance app.
        string mutexName = "e50cf829-f6b9-471e-8d9f-67eac3699f09";
        bool grantedOwnership;
        //we prefix the mutexName with "Local\\" to allow this to run under terminal services.
        //The "Local\\" prefix forces this into local user space.
        //If we want to forbid this in TS, use the "Global\\" prefix.
        Mutex singleInstanceMutex = new Mutex(true, "Global\\" + mutexName, out grantedOwnership);
        try
        {
            if (!grantedOwnership)
            {
                MessageBox.Show("Error: X is already running.\n\nYou can only run one copy of X at a time.", "X", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
                Application.Exit();
            }
            else
            {
                Application.Run(new X(args));
            }
        }
        finally
        {
            singleInstanceMutex.Close();
        }
    }

【讨论】:

  • 谢谢先生,这是我正在寻找的东西......我也使用过互斥锁......但请告诉我,我需要在其中调用第三方 exe......所以你知道它是总是提供一些特定的路径,例如:- D:\\Documents and Settings\\Administrator\\Desktop\\Drivers\\filename\\filename\\bin\\Debug\\filename.exe 所以我如何能够集中注意力每当我再次单击该按钮时,都会在此上..
【解决方案2】:

在 VB .NET 中有一个 IsSingleInstance 布尔属性可以为您完成这项工作。

在 VB 中(取自here):

Public Class Program
        Inherits Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase

       Public Sub New()
            Me.IsSingleInstance = True
        End Sub



End Class

在 C# 中使用它的方法如下(取自 here):

// SingleInstanceApplication.cs
class SingleInstanceApplication : WindowsFormsApplicationBase {

 // Must call base constructor to ensure correct initial 
 // WindowsFormsApplicationBase configuration
 public SingleInstanceApplication() {

  // This ensures the underlying single-SDI framework is employed, 
  // and OnStartupNextInstance is fired
  this.IsSingleInstance = true;
 }
}


// Program.cs
static class Program {
 [STAThread]
 static void Main(string[] args) {
  Application.EnableVisualStyles();
  SingleInstanceApplication application = 
   new SingleInstanceApplication();
  application.Run(args);
 }
}

确保在您的项目中引用 Microsoft.VisualBasic.dll。

【讨论】:

  • 这对处理普通的Application类有影响吗,比如设置Application.ThreadException等?也许互斥锁是一种更好的方式,因为您不需要改变您的应用架构?
  • (以上评论与c#有关)
  • 它仍然使用相同的底层消息循环内容,它只是对其调用的包装,因为它可能会启动主窗体,或者它可能会在现有应用程序处理来自的 args 信号后简单地退出新的那一个。一些设置代码可能会移动到包装器中的事件中,但如果您能找到合适的放置位置,则基本上仍应以相同的方式工作。
  • 它不适用于 Windows 来宾帐户。它抛出一个UnauthorizedAccessException
【解决方案3】:

打开您的项目属性(应用程序选项卡)并选中制作单实例应用程序选项。

在“应用程序”选项卡中,您还可以单击查看应用程序事件按钮,创建一个 ApplicationEvents.vb 类,您可以在其中处理第二个实例事件:

Partial Friend Class MyApplication
    Private Sub MyApplication_StartupNextInstance(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
        ' Bring First Instance to Foreground
        e.BringToForeground = True
        ' Pass Second Instance Command Line to First Instance
        AppShared.DoSomethingWithCommandLine(e.CommandLine)
    End Sub
End Class

【讨论】:

    【解决方案4】:

    Scott Hanselman 对此有很好的文章。代码是用 C# 编写的,但我想将它移植到 VB 会很容易。

    http://www.hanselman.com/blog/TheWeeklySourceCode31SingleInstanceWinFormsAndMicrosoftVisualBasicdll.aspx

    如果不能满足您的需求,这里还有一篇关于该主题的文章:

    http://www.codeproject.com/KB/cs/cssingprocess.aspx

    【讨论】:

      【解决方案5】:

      在 VB.NET 中,单个实例应用程序只是 a checkbox on the Project property page。您还可以捕获My.Application.StartupNextInstance 事件,让您的单个实例在另一个副本启动时执行某些操作。例如,这可以用于类似 MDI 的行为,即在原始实例中打开请求的文档。

      在幕后,它封装了大量互斥锁和 IPC goo - 请参阅 WindowsFormApplicationBase - 也可以在 C# 中使用。

      【讨论】:

        【解决方案6】:

        通过上面的提示,我了解了如何将我的应用程序设为单个实例,但我仍然需要去另一个网站了解具体方法。这是我如何做到这一点的简单图片。这很容易,我希望它可以帮助其他有同样需求的人,因为我确信 OP 在 7 年前解决了这个问题:

        【讨论】:

          【解决方案7】:

          使用Mutex。实际上,Mutex 可以用字符串命名,并且在 CLR 中是唯一的。

          示例代码:

          try
          {
          mutex = Mutex.OpenExisting(mutexName);
          //since it hasn’t thrown an exception, then we already have one copy of the app open.
          MessageBox.Show(”A copy of Todo 3.0 is already open. Please check your system tray (notification area).”,
          “Todo 3.0″, MessageBoxButtons.OK, MessageBoxIcon.Information);
          Environment.Exit(0);
          }
          catch (Exception Ex)
          {
          //since we didn’t find a mutex with that name, create one
          Debug.WriteLine(”Exception thrown:” + Ex.Message + ” Creating a new mutex…”);
          mutex = new Mutex(true, mutexName);
          }
          

          来自post

          【讨论】:

            【解决方案8】:

            如果您的应用程序在 VB.NET 2.0-3.5 中,保持程序的单个实例运行的最简单方法是使用“Windows 应用程序框架属性”。要到达那里,请右键单击您的项目名称并转到“属性”。在那里,选择“制作单实例应用程序”复选框。

            您还可以使用 ApplicationEvents.vb 向用户显示他们已经第二次运行您的程序。您可以通过选择“查看应用程序事件”按钮在同一属性窗口中轻松创建/查看它。在那里,您可以选择 MyApplication_StartupNextInstance 子并在那里输入代码,如下所示:

            Private Sub MyApplication_StartupNextInstance(ByVal sender As Object, ByVal e As Microsoft.VisualBasic.ApplicationServices.StartupNextInstanceEventArgs) Handles Me.StartupNextInstance
                MessageBox.Show("This program is already running.  If you do not see the program running, please check your " _
                    & "Windows Task Manager for this program name in the 'Processes' Tab." & vbNewLine & vbNewLine & "WARNING: " _
                    & " If you terminate the process, you will terminate the only instance of this program!", My.Application.Info.ProductName.ToString _
                    & " is Running!", MessageBoxButtons.OK, MessageBoxIcon.Warning)
            
            End Sub
            

            如果这有帮助,请告诉我!捷豹路虎

            【讨论】:

              【解决方案9】:

              为您的应用分配一些唯一标识符,例如硬编码的 guid,并创建一个 Mutex 实例,您可以在其中为该互斥量分配该标识符。如果它抛出异常,则表示您的应用程序已经在运行(因为它成功地创建了互斥锁)

              【讨论】:

                【解决方案10】:

                我认为将示例放在此处而不是链接会更容易。

                    [STAThread]
                    static void Main()
                    {
                        if (!IsAppAlreadyRunning())
                        {
                            Application.EnableVisualStyles();
                            Application.SetCompatibleTextRenderingDefault(false);
                            Application.Run(new Form1()); /* Change Form1 for your main Form */
                        }
                        else
                        {
                            MessageBox.Show("Application is already running!");
                        }
                    }
                
                    public static bool IsAppAlreadyRunning()
                    {
                        Process currentProcess = Process.GetCurrentProcess();
                        return (IsAppAlreadyRunning(currentProcess.Id, 
                                                    currentProcess.ProcessName));
                    }
                
                    private static bool IsAppAlreadyRunning(int ID, string Name)
                    {
                        bool isAlreadyRunning = false;
                        Process[] processes = Process.GetProcesses();
                        foreach (Process process in processes)
                        {
                            if (ID != process.Id)
                            {
                                if (Name == process.ProcessName)
                                {
                                    isAlreadyRunning = true;
                                    break;
                                }
                            }
                        }
                        return isAlreadyRunning;
                    }
                

                【讨论】:

                • 我想这个问题是如果有人重命名 .exe 他们可以运行两个实例。
                • 更具挑战性的部分是让现有的应用程序在命令运行时做一些有用的事情,例如将自身弹出到最前面(必要时减少最小化),或者在现有的应用程序。如果这些行为不是必需的,那么像这样的简单的已经运行的检查可能对您有用。
                【解决方案11】:

                最常见的模式是使用单例模式。由于您没有指明一种语言,我假设您在这里指的是 C# - 如果不是,那么大多数 OO 语言中的原则仍然相同。

                This的文章应该能给你一些帮助。

                【讨论】:

                • Pete 的链接中描述的技术在 VB.NET 中也能很好地工作。多年来,我一直将我的应用程序作为待办事项列表中的单例,所以这非常有帮助,因此 +1。
                • Singleton 是一个 class 模式。单个实例是 app 模式。
                • 文章链接已删除,此答案无济于事
                猜你喜欢
                • 2012-05-17
                • 2010-09-27
                • 2011-07-20
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多