代码之家  ›  专栏  ›  技术社区  ›  juan

在.NET中制作单实例应用程序的最佳方法是什么?[复制品]

  •  3
  • juan  · 技术社区  · 15 年前

    可能重复:
    What is the correct way to create a single instance application?
    Prevent multiple instances of a given app in .NET?

    是否检查是否存在同名的其他进程?(如果用户没有权限这样做怎么办?)

    将文件写入磁盘并在退出前将其删除?(异常终止怎么办?)

    这样做的最佳实践是什么?

    5 回复  |  直到 15 年前
        1
  •  6
  •   Alex McBride    15 年前

    您可以使用互斥体。

    bool firstInstance = true;
    using (Mutex mutex = new Mutex(true, "MyApplicationName", out firstInstance))
    {
        if (firstInstance)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
        else
        {
            // Another instance loaded
        }
    }
    
        2
  •  0
  •   David M    15 年前

    你可以使用 Process 班的 GetProcessesByName 方法查找另一个同名的正在运行的进程,如果找到该进程,则退出。

        3
  •  0
  •   John Fisher    15 年前

    通常,命名的互斥效果最好。以下是指向en的链接示例: http://www.iridescence.no/post/CreatingaSingleInstanceApplicationinC.aspx

        4
  •  0
  •   Yvo    15 年前

    我要看你用的技术。有很多解决方案,一些更适合WPF,一些适用于WinForms:

    • WindowsFormsApplicationsBase(我的首选方式)
    • 使用互斥(有点复杂)
    • 检查具有相同详细信息的流程(我不喜欢此流程)

    有关WindowsFormsApplications Base的更多信息:
    http://www.openwinforms.com/single_instance_application.html

    有关互斥和检查进程的详细信息:
    http://www.ravinderweb.com/page/Single-Instance-of-the-Application-using-C-Trick-and-Mutex.aspx

    我不会使用一个文件,它很容易出错,即使它不是应用程序的关键部分,没有文件访问权也可能导致程序中出现异常。

        5
  •  0
  •   to StackOverflow    15 年前

    有几种方法可以做到这一点,它们都有各自的优点和缺点,谷歌会给你很多关于它的讨论。

    你描述的方法有你提到的弱点。此外,还需要考虑希望实例具有多大的唯一性:

    • 每个窗台

    • 每台机器

    我有一个类,可以用来强制Windows窗体应用程序的每个WindowsStation使用一个实例。基本上,它使用p/invoke在启动期间执行以下操作,以防止使用互斥体的竞争条件:

    • 定义一个固定的唯一字符串来标识应用程序(如guid)

    • 获取一个互斥体,该互斥体的名称由唯一的字符串派生。

    • 使用p/invoke调用EnumWindows枚举所有主窗口。

    • 在EnumWindows回调中,依次使用p/invoke对每个窗口调用getprop,并将窗口句柄和唯一值作为参数传递。如果getprop检测到一个窗口具有您的唯一键(即应用程序的另一个实例),请激活它(postmessage(…sc_restore…),setForegroundWindow,setFocus),然后退出新实例。

    • 如果枚举所有窗口而没有找到上一个实例,请使用p/invoke调用setprop,为应用程序的主窗体窗口句柄设置唯一值。

    • 释放互斥体并继续启动。

    在我的用例中,这个解决方案比简单地在进程的生命周期中保持互斥要好,因为如果用户启动了第二个实例,它提供了激活前一个实例的方法,而不仅仅是退出。使用getprop/setprop可以在不依赖进程名称的情况下识别进程实例。