How to limit instances of a C# program in Citrix t

2019-05-21 17:42发布

问题:

I have a Windows Forms application with C# code as shown below (targeting .NET framework 4).

On my developer workstation, this code works to prevent me from launching multiple instances of the program. However, QA has a Citrix test environment where each user is still able to launch multiple instances.

What can be done to prevent a given user from running multiple instances in Citrix?

[STAThread]
static void Main(string[] args)
{
    bool isFirstInstance;
    Mutex m = new Mutex(true, "[App name goes here] mutex", out isFirstInstance);

    if (isFirstInstance)
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run();

        // Prevent the just-in-time (JIT) compiler from optimizing away our Mutex.
        // See: http://www.ai.uga.edu/mc/SingleInstance.html
        GC.KeepAlive(m);
    }
}

We want to limit the number of instances for technical reasons. The program uses self-hosted WCF to communicate with another process being run by the same user. We only want one instance of this program per user.

I don't know any details about the Citrix environment, but can inquire.

Thank you.

回答1:

Using either a Local or Global scoped mutex can be appropriate depending on exactly what behaviour you want.

Using a mutex with "Local\" will ensure you only have one instance running per session. However it will still be possible for your user to launch multiple sessions on the same server (depending on how your Citrix environment is configured), and hence have multiple instances of your app running in different sessions.

If you want to be 100% each user only has once instance per server then you need to use a Global mutex. However you need to make sure you name your mutex with state specific to the user, e.g.

string globalMutexName = string.Format(
    CultureInfo.InvariantCulture,
    "Global\\AppName~{0}~{1}~some-unique-guid",
    Environment.UserDomainName,
    Environment.UserName);

_machineLocalAppInstanceMutex = new System.Threading.Mutex(true, globalMutexName, out mutexIsNew);

if (!mutexIsNew)
{
    Shutdown();
}

Also I'd make the mutex a member of a class, typically your main App/Form class rather than using GC.KeepAlive



回答2:

Use a global mutex. The way your code is you can launch multiple instances of the program in different user sessions ... a global mutex will prevent that ...



回答3:

The simplest and best solution for that is to use a mutex, here is the code for that.

static void Main(string[] args)
{
        String mutexName = "MyApplication" + 
        System.Security.Principal.WindowsIdentity.GetCurrent().User.AccountDomainSid;

        Boolean createdNew;

        Mutex mutex = new Mutex(true, mutexName, out createdNew);

        if (!createdNew)
        {
            //If createdNew is false that means an instance of application is already running for this   
            // user.
            //So in this case stop the application from executing.
            return;
        }
        Console.ReadKey();
}

You can find a detailed explanation at this link.