简体   繁体   English

如何防止程序的多个实例同时运行?

[英]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 : 看看使用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 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. 在Bellow中,您可以找到简化检查多个实例的代码,并允许将起始参数从第二个实例转移到第一个实例。

    /// <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. 您可以检查FirstInstance属性是否创建了其他实例,并获得OtherInstanceCreated事件创建的其他实例的通知。

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) (据我所知)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 是否使用互斥锁来防止同一程序的多个实例安全运行? - Is using a Mutex to prevent multiple instances of the same program from running safe? 防止程序多个实例最安全的方法是什么? - What is the safest way to prevent multiple instances of a program? 防止运行一个Mono应用程序的多个实例 - Prevent running multiple instances of a mono app 防止服务器中的多个实例用户名相同 - Prevent multiple instances in server same username 运行一个程序的多个实例以加快过程? - Running multiple instances of a program to speed up process? 如何防止一个应用程序的两个实例同时做同样的事情? - How to prevent two instances of an application from doing the same thing at the same time? 在同一程序的多个实例之间同步 - Syncing between multiple instances of the same program 在单个AppDomain上运行多个应用程序实例时,如何防止属性覆盖? - How to prevent property overriding when running multiple app instances on single AppDomain? 如何使用LINQ防止多个用户同时更新一条记录 - How to prevent multiple users to update a record at the same time using LINQ 如何为同时运行的多个 ActionBlock 设置 CPU 优先级? - How to set CPU priority for multiple ActionBlocks running at the same time?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM