防止应用程序的多个实例

时间:2013-06-12 04:03:41

标签: c# winforms .net-4.0

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

6 个答案:

答案 0 :(得分:3)

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

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

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

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

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


修改

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

这可以使用TimeStamp和标志一起修复,如果TimeStamp早于某个时间,这意味着没有人使用该应用程序,因此可以使用它,这涉及在应用程序运行时每个时间段更新此TimeStamp,如心跳

答案 1 :(得分:1)

编辑:根据大众的需求,我会指出这个答案是对问题者提到互斥的回应,所以我假设他/她想要限制每台机器的用户数量。如果他/她想要限制网络中的总使用量,那么这不是这样做的方式。

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

  // 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;
  }

答案 2 :(得分:1)

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

如果您的应用程序未被授予独占写入权限,则表示您的应用程序可能已在网络上的其他位置运行。 (这里存在一些误报的风险:也许有人只是出于好奇而在编辑器中打开文件,或者有人更改了文件的权限。)

当应用程序终止时,它应该关闭文件句柄,从而释放文件的独占锁。

即使你的应用程序异常终止,操作系统也会清理进程,从而释放文件句柄,允许你的应用程序的另一个实例声明文件锁定。

(同样:这可能不适用于所有操作系统和网络文件服务器协议;我认为这应该适用于Windows网络和Samba文件服务器。)

答案 3 :(得分:0)

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

答案 4 :(得分:0)

如果您不想使用Mutex,那么您可以在应用程序代码中写入,检查机器上的所有进程,如果已找到相同的进程,则退出应用程序

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

但是这个解决方案有自己的缺点,因为你只用他的名字比较进程......

答案 5 :(得分:0)

好的,我会再做一次尝试,现在已经提供了额外的信息。

我不确定这是否可行,但为什么不在服务器上有一个文件用作“一次锁定一个文件”。在程序开始时,打开此文件进行写入。如果它有效,那应该对它进行独占锁定。如果它不起作用,则表示另一个程序当前打开文件进行写入,并且您说“抱歉,程序当前正在另一台计算机上运行”。如果它确实有效,那么只要程序正在运行,就会保持文件打开以进行写入。可能没有必要明确关闭文件,这应该在程序终止或崩溃时自动发生。