简体   繁体   中英

How to prevent multiple instances of a program running at the same time?

So I've created a program (not using forms) so it is a clean class, not a form. So, when the program starts, I want it to check Processes and if another one is found, kill itself. I have tried this...

static void checkDupe()
{
    string RunningProcess = Process.GetCurrentProcess().ProcessName;
    Process[] processes = Process.GetProcessesByName(RunningProcess);

    if (processes.Length > 1)
    {
        Process.GetCurrentProcess().Kill();
    }
}

Look at using a Mutex :

class Program
{
    static Mutex _m;

    static bool IsSingleInstance()
    {
    try
    {
        // Try to open existing mutex.
        Mutex.OpenExisting("PERL");
    }
    catch
    {
        // If exception occurred, there is no such mutex.
        Program._m = new Mutex(true, "PERL");

        // Only one instance.
        return true;
    }
    // More than one instance.
    return false;
    }

    static void Main()
    {
    if (!Program.IsSingleInstance())
    {
        Console.WriteLine("More than one instance"); // Exit program.
    }
    else
    {
        Console.WriteLine("One instance"); // Continue with program.
    }
    // Stay open.
    Console.ReadLine();
    }
}

The above example is taken from:

http://www.dotnetperls.com/mutex

it returns instance of running program by name

private static Process RunningInstance()
{
    var current = Process.GetCurrentProcess();
    var procName = current.ProcessName.Replace(@".vshost", string.Empty);
    var processes = Process.GetProcessesByName(procName);

    return processes.FirstOrDefault(t => t.Id != current.Id && current.SessionId == t.SessionId);
}

This is copied form my other answer: Syncing between multiple instances of the same program

Bellow you can find code that simplifies checking multiple instances as well as allow to transfer starting params from second instance to first one.

    /// <summary>
        /// Enforces single instance for an application.
        /// </summary>
        public class SingleInstance : IDisposable
        {
            #region Fields

            /// <summary>
            /// The synchronization context.
            /// </summary>
            private readonly SynchronizationContext synchronizationContext;

            /// <summary>
            /// The disposed.
            /// </summary>
            private bool disposed;

            /// <summary>
            /// The identifier.
            /// </summary>
            private Guid identifier = Guid.Empty;

            /// <summary>
            /// The mutex.
            /// </summary>
            private Mutex mutex;

            #endregion

            #region Constructors and Destructors

            /// <summary>
            /// Initializes a new instance of the <see cref="SingleInstance"/> class.
            /// </summary>
            /// <param name="identifier">
            /// An identifier unique to this application.
            /// </param>
            /// <param name="args">
            /// The command line arguments.
            /// </param>
            public SingleInstance(Guid identifier, IEnumerable<string> args)
            {
                this.identifier = identifier;

                bool ownsMutex;
                this.mutex = new Mutex(true, identifier.ToString(), out ownsMutex);

                this.synchronizationContext = SynchronizationContext.Current;

                this.FirstInstance = ownsMutex;

                if (this.FirstInstance)
                {
                    this.ListenAsync();
                }
                else
                {
                    this.NotifyFirstInstance(args);
                }
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="SingleInstance"/> class.
            /// </summary>
            /// <param name="identifier">
            /// An identifier unique to this application.
            /// </param>
            public SingleInstance(Guid identifier)
                : this(identifier, null)
            {
            }

            #endregion

            #region Public Events

            /// <summary>
            /// Event raised when arguments are received from successive instances.
            /// </summary>
            public event EventHandler<OtherInstanceCreatedEventArgs> OtherInstanceCreated;

            #endregion

            #region Public Properties

            /// <summary>
            /// Gets a value indicating whether this is the first instance of this application.
            /// </summary>
            public bool FirstInstance { get; private set; }

            #endregion

            #region Implemented Interfaces

            #region IDisposable

            /// <summary>
            /// The dispose.
            /// </summary>
            public void Dispose()
            {
                this.Dispose(true);
                GC.SuppressFinalize(this);
            }

            #endregion

            #endregion

            #region Methods

            /// <summary>
            /// Clean up any resources being used.
            /// </summary>
            /// <param name="disposing">
            /// True if managed resources should be disposed; otherwise, false.
            /// </param>
            protected virtual void Dispose(bool disposing)
            {
                if (this.disposed)
                {
                    return;
                }

                if (disposing)
                {
                    if (this.mutex != null && this.FirstInstance)
                    {
                        this.mutex.WaitOne();
                        this.mutex.ReleaseMutex();
                        this.mutex = null;
                    }
                }

                this.disposed = true;
            }

            /// <summary>
            /// Fires the OtherInstanceCreated event.
            /// </summary>
            /// <param name="arguments">
            /// The arguments to pass with the <see cref="OtherInstanceCreatedEventArgs"/> class.
            /// </param>
            protected virtual void OnOtherInstanceCreated(OtherInstanceCreatedEventArgs arguments)
            {
                EventHandler<OtherInstanceCreatedEventArgs> handler = this.OtherInstanceCreated;

                if (handler != null)
                {
                    handler(this, arguments);
                }
            }

            /// <summary>
            /// Listens for arguments on a named pipe.
            /// </summary>
            private void Listen()
            {
                try
                {
                    using (var server = new NamedPipeServerStream(this.identifier.ToString()))
                    {
                        using (var reader = new StreamReader(server))
                        {
                            server.WaitForConnection();
                            var arguments = new List<string>();

                            while (server.IsConnected)
                            {
                                arguments.Add(reader.ReadLine());
                            }

                            this.synchronizationContext.Post(o => this.OnOtherInstanceCreated(new OtherInstanceCreatedEventArgs(arguments)), null);                        
                        }
                    }

                    // start listening again.
                    this.Listen();
                }
                catch (IOException)
                {
                    // Pipe was broken, listen again.
                    this.Listen();
                }          
            }

            /// <summary>
            /// Listens for arguments being passed from successive instances of the applicaiton.
            /// </summary>
            private void ListenAsync()
            {
                Task.Factory.StartNew(this.Listen, TaskCreationOptions.LongRunning);
            }

            /// <summary>
            /// Passes the given arguments to the first running instance of the application.
            /// </summary>
            /// <param name="arguments">
            /// The arguments to pass.
            /// </param>
            private void NotifyFirstInstance(IEnumerable<string> arguments)
            {
                try
                {
                    using (var client = new NamedPipeClientStream(this.identifier.ToString()))
                    {
                        using (var writer = new StreamWriter(client))
                        {
                            client.Connect(200);

                            if (arguments != null)
                            {
                                foreach (string argument in arguments)
                                {
                                    writer.WriteLine(argument);
                                }
                            }
                        }
                    }
                }
                catch (TimeoutException)
                {
                    // Couldn't connect to server
                }
                catch (IOException)
                {
                    // Pipe was broken
                }
            }



 #endregion
    }

/// <summary>
/// Holds a list of arguments given to an application at startup.
/// </summary>
public class OtherInstanceCreatedEventArgs : EventArgs
{
    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="OtherInstanceCreatedEventArgs"/> class.
    /// </summary>
    /// <param name="args">
    /// The command line arguments.
    /// </param>
    public OtherInstanceCreatedEventArgs(IEnumerable<string> args)
    {
        this.Args = args;
    }

    #endregion

    #region Public Properties

    /// <summary>
    /// Gets the startup arguments.
    /// </summary>
    public IEnumerable<string> Args { get; private set; }

    #endregion
}

Then in your main class you can create instance of of class that will stay until aplication is running. You can check if other instance is created by FirstInstance property, And get notified of other instance created by OtherInstanceCreated event.

Same mutex idea, but simpler code:

        bool SingleInstance;
        var mut = new Mutex(true,"UniqueName", out SingleInstance);
        if (SingleInstance) {
           //Run
        } else {
           //Exit
        }

When application exists, mutex is destroyed, no need to release it or dispose it or anything.

(AFAIK)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM