防止应用程序的多个实例

本文关键字:实例 应用程序 | 更新日期: 2023-09-27 18:17:54

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

防止应用程序的多个实例

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

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

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

但是如果锁定该标志的应用程序被关闭(通常情况下),这将锁定应用程序。

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

使用一个文件来控制标志,当应用程序关闭时发出——通常:

这可以使用TimeStamp和标志来修复,如果TimeStamp比某个时间更老,这意味着没有人在使用应用程序,因此它被允许使用它,这涉及在应用程序运行时更新这个TimeStamp的每个时间段,如心跳

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

这是我目前使用的:

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

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

如果您的应用程序没有被授予独占写访问权限,这意味着您的应用程序可能已经在网络上的其他地方运行。(这里有一些误报的风险:也许有人出于好奇在编辑器中打开了文件,或者有人更改了文件的权限。)

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

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

(再次强调:这可能不适用于所有操作系统和网络文件服务器协议;我认为这应该在Windows网络和Samba文件服务器上工作。)

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

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

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

好的,既然已经提供了额外的信息,我将再试一次。

我不知道这是否可行,但为什么不在服务器上有一个文件,用作一种"一次一个锁定文件"。在程序开始时,打开这个文件进行写入。如果它起作用,那么应该对它设置一个排他锁。如果它不工作,这表明另一个程序当前正在打开文件以进行写入,并且您说"对不起,程序当前正在另一台机器上运行"。如果它确实有效,那么只要程序正在运行,就保持文件打开以供写入。可能不需要显式地关闭文件,这应该在程序终止或崩溃时自动发生。