Click here to Skip to main content
16,020,669 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
To run a single instance of a program, I use the following approach, which is recommended in this link rather than the approach presented here.
C#
using System;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Threading;
using System.Windows;

namespace My_App
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    static class GlobalMutex
    {
        public static void SingleGlobalInstance()
        {
            string AppGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();
            string MutexId = string.Format("Global\\{{{0}}}", AppGuid);
            bool CreatedNew;
            var AllowEveryoneRule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
            var SecuritySettings = new MutexSecurity();
            SecuritySettings.AddAccessRule(AllowEveryoneRule);
            using (var mutex = new Mutex(false, MutexId, out CreatedNew, SecuritySettings))
            {
                var HasHandle = false;
                try
                {
                    try
                    {
                        HasHandle = mutex.WaitOne(5000, false);
                        switch (HasHandle)
                        {
                            case false:
                                throw new TimeoutException("Timeout waiting for exclusive access");
                        }

                    }
                    catch (AbandonedMutexException)
                    {
                        HasHandle = true;
                    }
                }
                finally
                {
                    switch (HasHandle)
                    {
                        case true:
                            mutex.ReleaseMutex();
                            break;
                    }
                }
            }
        }
    }

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            GlobalMutex.SingleGlobalInstance();
            base.OnStartup(e);
        }
    }
}

But I get the following error:
Index was outside the bounds of the array
in
Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString()

What is the cause of this error and how can it be resolved?
I use the following tools:
• .NET Framework 4.5
• WPF

Thank you for your time.
Best regards,
Reza Jaferi

What I have tried:

C#
public MainWindow()
{
    //class GlobalMutex
    InitializeComponent();
    GlobalMutex GM = new GlobalMutex();
    GM.SingleGlobalInstance();
}
Posted
Updated 31-Aug-22 1:27am
v4

C#
string AppGuid = ((GuidAttribute)Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(GuidAttribute), false).GetValue(0)).Value.ToString();

What is going to hinder your debugging, and therefore make your code unsupportable, is that you're chaining (cramming) all these method and property calls in a single statement. NEVER DO THIS!! It makes your code difficult to debug since you cannot see the intermediate return values being passed down the chain and cannot see where the problem occurs.

As for why the code is failing, does your app even have a GUID? Open the Properties node of your project in Solution Explorer, click on the Application tab, then on the "Assembly Information..." button. In the dialog that appears, is the GUID field filled in with a VALID guid? For example: 69D69F94-225B-4B31-B149-04E8A1183D05
 
Share this answer
 
v2
Comments
Reza jafery 31-Aug-22 7:16am    
"What is going to hinder your debugging, ... " It is useful for debugging the app, but once it has been debugged and completed, I prefer to code as shown above (chained) because the fewer variables defined, the less RAM is required.
Dave Kreskowiak 31-Aug-22 9:49am    
You're not really saving RAM with that technique. Once the code is compiled in Release, optimizations will take care of the RAM. Besides, nobody cares about, what, 16 bytes, you think you're going to save.
Reza jafery 31-Aug-22 10:42am    
Although 16 bytes may appear to be a small amount, when we have a large design with a large number of variables, after debugging we can save a few megabytes by using this approach instead of GC.Collect.
Dave Kreskowiak 31-Aug-22 10:44am    
Seriously, you're not really saving anything. The compilers optimizer is already doing it for you.

Chances are really high, if you're calling GC.Collect, you're doing something wrong.
Reza jafery 31-Aug-22 10:55am    
I know that the compiler actually performs this, however, let's say you have a project where 200 variables are momentarily used and then terminated after the application finishes. In such cases, this approach would also be helpful.
Simple: GetCustomAttributes is returning an empty collection, so your attempt to get the zeroth element is failing.
Use the debugger to find out why for your app, we can't run your code under exactly the same circumstances you can.
 
Share this answer
 
Comments
Reza jafery 30-Aug-22 17:10pm    
Thanks for the answer. I know that this collection is empty, but why?
OriginalGriff 30-Aug-22 17:39pm    
"Use the debugger to find out why for your app, we can't run your code under exactly the same circumstances you can."

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900