Одноэкземплярное приложение Windows Forms и как получить ссылку на него?

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

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

Проще говоря: как я могу выйти из текущего запущенного приложения, когда кто-то пытается запустить то же приложение с параметром командной строки exit?

bool quit = (args.Length > 0 && args[0] == "quit") ? true : false;
using (Mutex mutex = new Mutex(false, sExeName))
{
    if (!mutex.WaitOne(0, true)) 
    {
        if (quit)
        {
            // This is the tricky part?
            // How can I get reference to "previous" launced 
            // Windows Forms application and call it's Exit() method.
        }
    } 
    else 
    {
        if (!quit)
        {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }
}

person Clack    schedule 30.03.2009    source источник


Ответы (4)


Платформа .NET предлагает для этого очень хорошее универсальное решение. Проверьте нижнюю часть этой статьи журнала MSDN. Используйте обработчик событий StartupNextInstanceHandler () для передачи произвольных команд запущенному экземпляру, например «выйти».

person Hans Passant    schedule 31.03.2009
comment

Разве это не слишком усложняет ситуацию? Можете ли вы вместо закрытия существующего экземпляра и запуска нового просто повторно активировать существующий экземпляр? В любом случае приведенный ниже код должен дать вам некоторые идеи о том, как это сделать ...?

Process thisProcess = Process.GetCurrentProcess();
        Process[] allProcesses = Process.GetProcessesByName(thisProcess.ProcessName);
        Process otherProcess = null;
        foreach (Process p in allProcesses )
        {
            if ((p.Id != thisProcess.Id) && (p.MainModule.FileName == thisProcess.MainModule.FileName))
            {
                otherProcess = p;
                break;
            }
        }

       if (otherProcess != null)
       {
           //note IntPtr expected by API calls.
           IntPtr hWnd = otherProcess.MainWindowHandle;
           //restore if minimized
           ShowWindow(hWnd ,1);
           //bring to the front
           SetForegroundWindow (hWnd);
       }
        else
        {
            //run your app here
        }

Есть еще один вопрос по этому поводу здесь

person Matt    schedule 30.03.2009
comment
Оно работает! Внутри 'if (otherProccess! = Null)' я поставил: 'MessageBox.Show (приложение уже запущено!); thisProcess.Kill (); '. Спасибо - person Silvio Delgado; 02.09.2014

Это довольно быстрое и грязное решение, которое вы, вероятно, захотите доработать:

[STAThread]
static void Main()
{
    var me = Process.GetCurrentProcess();
    var otherMe = Process.GetProcessesByName(me.ProcessName).Where(p => p.Id != me.Id).FirstOrDefault();

    if (otherMe != null)
    {
        otherMe.Kill();
    }
    else
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

Если экземпляр приложения уже запущен, этот процесс завершается; в противном случае приложение запускается нормально.

person Tormod Fjeldskår    schedule 30.03.2009

Думаю, самый простой способ следующий

см. ссылку

http://codenicely.blogspot.com/2010/04/creating-forms-object.html

person Khalid Rafique    schedule 15.02.2012