C# 防止应用程序的多个实例

C# 防止应用程序的多个实例,c#,winforms,.net-4.0,C#,Winforms,.net 4.0,我在共享驱动器中有一个c#应用程序可执行文件。这允许访问共享驱动器的用户(3)打开可执行文件。现在要求不超过一个人可以同时运行可执行文件。我环顾四周,解决方案似乎是使用互斥,我不太明白。此问题是否有其他解决方案/解决方法。使用命名互斥锁。这是正常的做法。从程序中创建一个命名的互斥体(确保名称唯一)。构造函数将使用out bool createdNew参数告诉您是创建了新的互斥还是打开了现有的互斥。如果此标志为false,则程序的一个实例已在运行。编辑:根据流行的要求,我将指出此答案是对提问者提到

我在共享驱动器中有一个c#应用程序可执行文件。这允许访问共享驱动器的用户(3)打开可执行文件。现在要求不超过一个人可以同时运行可执行文件。我环顾四周,解决方案似乎是使用互斥,我不太明白。此问题是否有其他解决方案/解决方法。

使用命名互斥锁。这是正常的做法。从程序中创建一个命名的互斥体(确保名称唯一)。构造函数将使用
out bool createdNew
参数告诉您是创建了新的互斥还是打开了现有的互斥。如果此标志为false,则程序的一个实例已在运行。

编辑:根据流行的要求,我将指出此答案是对提问者提到互斥的回应,因此我假设他/她希望限制每台机器的用户数。如果他/她想限制网络中的总使用量,那么这不是实现的方法

以下是我目前正在使用的内容:

  // Mutex object used to determine if there are multiple instances of this program running. 
  //  Note that this is a reference to a .Net Mutex object, not the Windows mutex itself.
  private static Mutex _onlyOneInstanceMutex;



  /// <summary>
  /// Method to test that there is not another instance of the program already running on this 
  /// machine, or at least in this Terminal Services session or Windows Vista / Windows 7 
  /// concurrent sessions session. If there is, a message box-style localized error message is 
  /// displayed and the value false is returned. This implies that this method should only be 
  /// used in WinForms programs.
  /// 
  /// This implementation uses a .Net Mutex object in public storage to prevent it from being 
  /// garbage-collected. The name of the associated Windows mutex is simply the program name as 
  /// provided by the caller. Neither the .Net Mutex object nor the Windows mutex are ever 
  /// explicitly released; they remain in existence, perhaps in an "abandoned" state, until the 
  /// process that created them terminates.
  /// </summary>
  /// <returns>false if another instance running, otherwise true</returns>
  [SuppressMessage("Microsoft.Reliability", "CA2004:RemoveCallsToGCKeepAlive",
                   Justification = "Not sure if this is correct or not.")]
  public static bool TestOnlyOneInstance(string programName)
  {
     // Funny construct to prevent the Mutex from being garbage collected
     GC.KeepAlive(_onlyOneInstanceMutex);

     // Test if we are the first instance, and if so create the Windows mutex, making it 
     //  impossible for subsequent instances to successfully create their mutex
     bool firstInstance;
     _onlyOneInstanceMutex = new Mutex(false, programName, out firstInstance);
     if (firstInstance)
        return true;

     // Display a (possibly localized) error message, then return
     string errorMessage = MLocalizer.GetString("Error1", 
           "Another instance of this program is already running on this machine.") +
         "\n" + MLocalizer.GetString("Error2",
                                     "You cannot run two instances at the same time.") +
         "\n" + MLocalizer.GetString("Error3", "Please use the other instance.");
     MessageBox.Show(errorMessage, programName, MessageBoxButtons.OK, MessageBoxIcon.Error);
     return false;
  }
//用于确定此程序是否有多个实例正在运行的互斥对象。
//请注意,这是对.Net互斥对象的引用,而不是对Windows互斥对象本身的引用。
专用静态互斥锁(仅限安装互斥锁);;
/// 
///方法来测试此服务器上是否没有另一个程序实例正在运行
///计算机,或至少在此终端服务会话或Windows Vista/Windows 7中
///并发会话。如果存在,则显示消息框样式的本地化错误消息
///显示并返回值false。这意味着此方法只应
///在WinForms程序中使用。
/// 
///此实现在公共存储中使用.Net互斥对象以防止其被删除
///垃圾收集。关联的Windows互斥体的名称只是程序名
///由来电者提供。无论是.Net互斥对象还是Windows互斥对象都不可用
///明确发布;它们仍然存在,也许处于“被遗弃”的状态,直到
///创建它们的进程终止。
/// 
///如果另一个实例正在运行,则为false,否则为true
[SuppressMessage(“Microsoft.Reliability”,“CA2004:RemoveCallsToGCKeepAlive”,
justion=“不确定这是否正确。”)]
公共静态bool TestOnlyOneInstance(字符串程序名)
{
//防止互斥锁被垃圾收集的有趣构造
GC.KeepAlive(_onlyOneInstanceMutex);
//测试我们是否是第一个实例,如果是,则创建Windows互斥体,使其
//后续实例不可能成功创建互斥体
布尔一审;
_onlyOneInstanceMutex=新的互斥(false,programName,out firstInstance);
如果(第一次)
返回true;
//显示(可能是本地化的)错误消息,然后返回
string errorMessage=MLocalizer.GetString(“Error1”,
“此程序的另一个实例已在此计算机上运行。”)+
“\n”+MLocalizer.GetString(“错误2”,
“不能同时运行两个实例。”)+
“\n”+MLocalizer.GetString(“Error3”,“请使用其他实例”);
显示(errorMessage,programName,MessageBoxButtons.OK,MessageBoxIcon.Error);
返回false;
}

您可以创建一个非常小的控制文件,一个任何格式的文件,txt或XML 添加此文件标志

任何实例都会启动,如果标志为true,则退出应用程序 否则,将标志设置为true

当您的应用程序退出并将标志设置为true时,将标志恢复为false

但是,如果锁定标志的应用程序正常关闭,这将锁定应用程序

所以最好的方法是使用互斥锁,或者在应用程序连接到的公共位置上创建一个小型服务器应用程序,并以与使用文件相同的方式使用它来设置标志;这样,即使应用程序以非正常方式关闭,服务器也能够检测到这一点,并且它仍将释放标志状态以允许其他实例启动


编辑:

使用文件控制标志,在应用程序正常关闭时发出:


这可以通过使用
时间戳
和标志来修复,如果
时间戳
早于某个时间,这意味着没有人在使用应用程序,因此允许使用它,这涉及在应用程序运行的每个时间段更新此
时间戳
,就像心跳一样,若您不想使用互斥锁,那个么您可以在应用程序代码中写入检查机器上所有进程的代码,若已经找到相同的进程,那个么退出应用程序

System.Diagnostic.Process.GetProcesses(); // get a array of processes

但是这个解决方案也有自己的缺点,因为您只按他的名字来比较流程…

好的,既然提供了额外的信息,我将进行另一次尝试


我不知道这是否可行,但为什么不在服务器上设置一个文件,作为一种“一次一个锁定文件”使用呢。在程序开始时,打开此文件进行写入。如果可以的话,应该在它上面设置一个独占锁。如果它不工作,则表示另一个程序当前已打开该文件进行写入,您会说“对不起,该程序当前正在另一台计算机上运行”。如果它工作,则在该程序运行期间保持该文件打开进行写入。可能不需要显式关闭文件,当程序终止或崩溃时会自动关闭文件。

如果您的操作系统和/或网络文件系统支持此操作,您可以在网络文件服务器上创建一个空文件(如果它还不存在)并在应用程序启动时请求独占写入访问权限

如果您的应用程序未被授予独占写访问权限,则表示