且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

检查应用程序是否已经在当前用户下运行

更新时间:2023-01-28 08:41:33

通常接受的一种方法是使用命名的互斥锁.通过创建一个命名的互斥锁,您可以确定另一个实例是否已经在运行并关闭新实例.

此代码应为您提供所需的结果.假定所有这些都在可执行文件的主入口点中.

bool createdMutex;
using (var processMutex = new System.Threading.Mutex(false, "Some name that is unique for the executable", out createdMutex)) {

   if (!createdMutex)
     ; // some other instance of the application is already running (or starting up). You may want to bring the other instance to foreground (assuming this is a GUI app)
   else 
   {
      // this is the process to actually run..
      // do application init stuff here
   }
}

请注意,我在此处键入了代码,因此可能存在语法错误,错别字和其他偶然的误导.

根据注释中的请求,以下是选择互斥锁名称的一些说明:

如果要在每个终端服务器会话中将应用程序限制为一个实例,请选择该应用程序唯一的互斥体名称.

如果要将应用程序限制为终端服务器会话中每个用户"的单个实例,请选择该应用程序唯一的互斥体名称,并附加用户的SID. WindowsIdentity.GetCurrent()将为您提供SecurityIdentifier.

如果要将应用程序限制为每个用户一个实例,而不论哪个终端服务器会话,请选择一个互斥量名称,该名称对于包含用户SID的应用程序是唯一的,并在名称前加上"Global \"./p>

如果要将应用程序限制为每个服务器一个实例,请选择该应用程序唯一的互斥体名称,并以"Global \"作为前缀.

重要的是要注意,尽管终端服务器会话与单个用户相关联,但这并不意味着该会话中运行的所有应用程序都与该用户相关联(考虑运行方式"选项).

In a terminal server situation I want to make sure only 1 instance of the application runs for each user.

What is the best way to do this?

Here is what i'm currently using but it seems like it isn't working as intended. I can't be 100% on that.

int SID = Process.GetCurrentProcess().SessionId;

Process current_process = Process.GetCurrentProcess();
int proc_count = 0;

foreach (Process p in Process.GetProcessesByName(current_process.ProcessName))
{
    proc_count++;
    if (p.SessionId.Equals(SID))
    {
        if (proc_count > 1)
        {
            Application.Current.Shutdown();
            return;
        }
    }
}

UPDATE To help clarify by the comments I have read I think it needs to be off the session ID because not all clients will follow one physical person per username and there for the user can be logged into the server multiple times.

The generally accepted way to do this is with a named mutex. By creating a named mutex you can determine if another instance is already running and shutdown the new instance.

This code should give you the desired result. All of this is assumed to be in the executable's main entry point.

bool createdMutex;
using (var processMutex = new System.Threading.Mutex(false, "Some name that is unique for the executable", out createdMutex)) {

   if (!createdMutex)
     ; // some other instance of the application is already running (or starting up). You may want to bring the other instance to foreground (assuming this is a GUI app)
   else 
   {
      // this is the process to actually run..
      // do application init stuff here
   }
}

Be warned, I typed the code here, so there may be syntax errors, typos and other accidental misdirection.

As request in the comments, here is some direction on choosing the name of the mutex:

If you want to limit the application to a single instance per terminal server session, then choose a mutex name that is unique to the application.

If you want to limit the application to a single instance per "user" within a terminal server session, choose a mutex name that is unique to the application and append the user's SID. WindowsIdentity.GetCurrent() will provide you with the SecurityIdentifier.

If you want to limit the application to a single instance per user, regardless of which terminal server session, choose a mutex name this is unique to the application with the user's SID included and prefix the name with "Global\".

If you want to limit the application to a single instance per server, choose a mutex name that is unique to the application and prefix with "Global\".

It is important to note that while a terminal server session is associated with a single user, that does not mean that all of the applications running in the session are associated with that user (consider "Run As" options).