Запустить один экземпляр из приложения - PullRequest
4 голосов
/ 25 мая 2009

У меня есть приложение для Windows (C #), и мне нужно настроить его для одновременного запуска одного экземпляра из приложения. Это означает, что один пользователь щелкнул файл .exe, и приложение запускается, а пользователь не закрывается первый экземпляр приложения, которое запускается и требует запуска следующего экземпляра, поэтому он должен отображаться первым экземпляром, а не открывать новый.

Может ли кто-нибудь помочь мне, как это сделать?

заранее спасибо

Ответы [ 7 ]

10 голосов
/ 25 мая 2009

Я часто решаю эту проблему, проверяя другие процессы с тем же именем. Преимущество / недостаток этого заключается в том, что вы (или пользователь) можете «отойти» от проверки, переименовав исполняемый файл. Если вы не хотите, чтобы вы могли использовать возвращаемый объект Process.

  string procName = Process.GetCurrentProcess().ProcessName;
  if (Process.GetProcessesByName(procName).Length == 1)
  {
      ...code here...
  }

Это зависит от ваших потребностей, я думаю, что удобно обходить проверку без перекомпиляции (это серверный процесс, который иногда запускается как служба).

4 голосов
/ 25 мая 2009

Команда VB.Net уже внедрила решение. Вам нужно взять зависимость от Microsoft.VisualBasic.dll, но если это вас не беспокоит, то это ИМХО хорошее решение См. Конец следующей статьи: Приложения для одного экземпляра

Вот соответствующие части из статьи:

1) Добавить ссылку на Microsoft.VisualBasic.dll 2) Добавьте следующий класс в ваш проект.

public class SingleInstanceApplication : WindowsFormsApplicationBase
{
    private SingleInstanceApplication()
    {
        base.IsSingleInstance = true;
    }

    public static void Run(Form f, StartupNextInstanceEventHandler startupHandler)
    {
        SingleInstanceApplication app = new SingleInstanceApplication();
        app.MainForm = f;
        app.StartupNextInstance += startupHandler;
        app.Run(Environment.GetCommandLineArgs());
    }
}

Откройте Program.cs и добавьте следующий оператор using:

using Microsoft.VisualBasic.ApplicationServices;

Измените класс на следующий:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        SingleInstanceApplication.Run(new Form1(), StartupNextInstanceEventHandler);
    }

    public static void StartupNextInstanceEventHandler(object sender, StartupNextInstanceEventArgs e)
    {
        MessageBox.Show("New instance");
    }
}
1 голос
/ 25 мая 2009

У нас была точно такая же проблема. Мы попробовали процессный подход, но он потерпит неудачу, если пользователь не имеет права читать информацию о других процессах, т.е. Итак, мы реализовали решение ниже.

В основном мы пытаемся открыть файл для эксклюзивного чтения. Если это не удается (так как экземпляр anohter уже сделал это), мы получаем исключение и можем выйти из приложения.

        bool haveLock = false;
        try
        {
            lockStream = new System.IO.FileStream(pathToTempFile,System.IO.FileMode.Create,System.IO.FileAccess.ReadWrite,System.IO.FileShare.None);
            haveLock = true;
        }
        catch(Exception)
        {
            System.Console.WriteLine("Failed to acquire lock. ");
        }
        if(!haveLock)
        {
            Inka.Controls.Dialoge.InkaInfoBox diag = new Inka.Controls.Dialoge.InkaInfoBox("App has been started already");
            diag.Size = new Size(diag.Size.Width + 40, diag.Size.Height + 20);
            diag.ShowDialog();
            Application.Exit();
        }
1 голос
/ 25 мая 2009

Редактировать: После того, как вопрос был изменен, чтобы включить c #. Мой ответ работает только для приложения vb.net

установите флажок Сделать одно приложение , чтобы запретить пользователям запускать несколько экземпляров вашего приложения. Установка по умолчанию для этого флажка снята, что позволяет запускать несколько экземпляров приложения.

Вы можете сделать это из Project -> Properties -> вкладка приложения

Источник

0 голосов
/ 13 июня 2017

Я нашел этот код , это работает!

 /// <summary>
        /// The main entry point for the application.
        /// Limit an app.to one instance
        /// </summary>
        [STAThread]
        static void Main()
        {
            //Mutex to make sure that your application isn't already running.
            Mutex mutex = new System.Threading.Mutex(false, "MyUniqueMutexName");
            try
            {
                if (mutex.WaitOne(0, false))
                {
                    // Run the application
                    Application.EnableVisualStyles();
                    Application.SetCompatibleTextRenderingDefault(false);
                    Application.Run(new Form1());
                }
                else
                {
                    MessageBox.Show("An instance of the application is already running.",
                        "An Application Is Running", MessageBoxButtons.OK, MessageBoxIcon.Information);
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "Application Error 'MyUniqueMutexName'", 
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            finally
            {
                if (mutex != null)
                {
                    mutex.Close();
                    mutex = null;
                }
            }
        }
0 голосов
/ 25 ноября 2016

Я бы использовал Mutex для этого сценария. Кроме того, Semaphore также будет работать (но Mutex кажется более подходящим).

Вот мой пример (из приложения WPF, но те же принципы должны применяться к другим типам проектов):

public partial class App : Application
{
    const string AppId = "MY APP ID FOR THE MUTEX";
    static Mutex mutex = new Mutex(false, AppId);
    static bool mutexAccessed = false;

    protected override void OnStartup(StartupEventArgs e)
    {
        try
        {
            if (mutex.WaitOne(0))
                mutexAccessed = true;
        }
        catch (AbandonedMutexException)
        {
            //handle the rare case of an abandoned mutex
            //in the case of my app this isn't a problem, and I can just continue
            mutexAccessed = true;
        }

        if (mutexAccessed)
            base.OnStartup(e);
        else
            Shutdown();
    }

    protected override void OnExit(ExitEventArgs e)
    {
        if (mutexAccessed)
            mutex?.ReleaseMutex();

        mutex?.Dispose();
        mutex = null;
        base.OnExit(e);
    }
}
0 голосов
/ 25 мая 2009

Если вы используете C #

        static Mutex mx;
        const string singleInstance = @"MU.Mutex";
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main()
        {
            try
            {
                System.Threading.Mutex.OpenExisting(singleInstance);
                MessageBox.Show("already exist instance");
                return;
            }
            catch(WaitHandleCannotBeOpenedException)
            {
                mx = new System.Threading.Mutex(true, singleInstance);

            }
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
...