如何实现单实例单机应用?

问题描述 投票:0回答:4

我必须限制我的 .net 4 WPF 应用程序,以便它每台机器只能运行一次。请注意,我说的是每台机器,而不是每会话。
到目前为止,我使用简单的互斥体实现了单实例应用程序,但不幸的是,这样的互斥体是每个会话的。

有没有办法创建机器范围的互斥体,或者是否有其他解决方案来实现每台机器应用程序的单个实例?

c# .net mutex single-instance
4个回答
14
投票

我将使用必须在应用程序的生命周期中保留的全局互斥对象来完成此操作。

MutexSecurity oMutexSecurity;

//Set the security object
oMutexSecurity = new MutexSecurity();
oMutexSecurity.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.BuiltinUsersSid, null), MutexRights.FullControl, AccessControlType.Allow));

//Create the global mutex and set its security
moGlobalMutex = new Mutex(True, "Global\\{5076d41c-a40a-4f4d-9eed-bf274a5bedcb}", bFirstInstance);
moGlobalMutex.SetAccessControl(oMutexSecurity);

如果这是全局运行的应用程序的第一个实例,则返回

bFirstInstance
。如果您省略了互斥锁的全局部分或将其替换为本地互斥锁,则互斥锁将仅适用于每个会话(这可能是您当前代码的工作方式)。

我相信我首先从Jon Skeet那里得到了这项技术。

有关 Mutex 对象的 MSDN 主题解释了 Mutex 对象的两个范围,并强调了为什么这在使用终端服务时很重要(请参阅倒数第二个注释)。


3
投票

我认为您需要做的是使用系统信号来跟踪应用程序的实例。

如果您使用接受名称的构造函数创建信号量对象,则它将与该名称的操作系统信号量相关联。

命名系统信号量在整个操作系统中都是可见的,可用于同步进程的活动。

编辑:请注意,我不知道这种方法是否适用于计算机上的多个窗口会话。我认为它应该作为操作系统级别的构造,但我不能肯定地说,因为我还没有这样测试过。

编辑2:我不知道这一点,但在阅读了Stevo2000的答案后,我也做了一些查找,我认为使对象适用于全局命名空间的“Global\”前缀也适用于信号量和信号量,如果以这种方式创建,应该可以工作。


2
投票

您可以在 %PROGRAMDATA% 中的某个位置打开具有独占权限的文件 启动的第二个实例将尝试打开同一文件,如果它已经打开,则失败。


1
投票

使用注册表怎么样?

  1. 您可以创建一个
    registry entry under HKEY_LOCAL_MACHINE
  2. 如果应用程序启动或未启动,则将该值设置为
    flag
  3. Encrypt the key
    使用某种标准的
    symmetric key encryption
    方法,以便其他人无法篡改该值。
  4. On application start-up check for the key
    并中止
© www.soinside.com 2019 - 2024. All rights reserved.