Как перезапустить приложение C # WinForm? - PullRequest
77 голосов
/ 23 апреля 2009

Разработка приложения WinForm для C # .NET 2.0. Нужно приложение, чтобы закрыть и перезапустить себя.

Application.Restart();

Приведенный выше метод имеет значение , которое оказалось ненадежным .

Как лучше перезапустить приложение?

Ответы [ 20 ]

52 голосов
/ 17 сентября 2010

Если вы находитесь в главной форме приложения, попробуйте использовать

System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app
43 голосов
/ 23 февраля 2011

Гораздо более простой подход, который работал для меня:

Application.Restart();
Environment.Exit(0);

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

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

Код выхода 0 в Environment.Exit(0); указывает на чистое отключение. Вы также можете выйти с 1, чтобы указать, что произошла ошибка.

38 голосов
/ 09 сентября 2009

К сожалению, вы не можете использовать Process.Start () для запуска экземпляра текущего запущенного процесса. Согласно документу Process.Start (): «Если процесс уже запущен, дополнительный ресурс процесса не запускается ...»

Этот метод будет хорошо работать в отладчике VS (потому что VS совершает какое-то волшебство, которое заставляет Process.Start думать, что процесс еще не запущен), но завершится неудачей, если не будет работать под отладчиком. (Обратите внимание, что это может зависеть от ОС - я помню, что в некоторых моих тестах он работал на XP или Vista, но я просто помню, что запускал его под отладчиком.)

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

Редактировать: Использование второго приложения работает. Все, что я сделал во втором приложении, было:

    static void RestartApp(int pid, string applicationName )
    {
        // Wait for the process to terminate
        Process process = null;
        try
        {
            process = Process.GetProcessById(pid);
            process.WaitForExit(1000);
        }
        catch (ArgumentException ex)
        {
            // ArgumentException to indicate that the 
            // process doesn't exist?   LAME!!
        }
        Process.Start(applicationName, "");
    }

(Это очень упрощенный пример. Реальный код имеет множество проверок работоспособности, обработки ошибок и т. Д.)

16 голосов
/ 24 ноября 2011

Я мог бы опоздать на вечеринку, но вот мое простое решение, и оно работает как шарм с каждым приложением, которое у меня есть:

        try
        {
            //run the program again and close this one
            Process.Start(Application.StartupPath + "\\blabla.exe"); 
            //or you can use Application.ExecutablePath

            //close this one
            Process.GetCurrentProcess().Kill();
        }
        catch
        { }
11 голосов
/ 07 января 2010

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

Что я делаю, так это запускаю новый процесс с идентификатором процесса старого процесса (который запускает перезапуск) в качестве аргумента строки cmd:

// Shut down the current app instance.
Application.Exit();

// Restart the app passing "/restart [processId]" as cmd line args
Process.Start(Application.ExecutablePath, "/restart" + Process.GetCurrentProcess().Id);

Затем, когда новое приложение запускается, я сначала анализирую аргументы строки cm и проверяю, есть ли там флаг перезапуска с processId, затем жду выхода из этого процесса:

if (_isRestart)
{
   try
   {
      // get old process and wait UP TO 5 secs then give up!
      Process oldProcess = Process.GetProcessById(_restartProcessId);
      oldProcess.WaitForExit(5000);
   }
   catch (Exception ex)
   { 
      // the process did not exist - probably already closed!
      //TODO: --> LOG
   }
}

Я явно не показываю все проверки безопасности, которые у меня есть, и т. Д.

Даже если это не идеально - я считаю это приемлемой альтернативой, чтобы вам не приходилось устанавливать отдельное приложение только для перезапуска.

6 голосов
/ 01 апреля 2013

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

Application.Restart();
Environment.exit(int errorcode);

Вы можете создать перечисление кода ошибки, для которого вы можете использовать его с умом.
Другой способ - просто выйти из приложения и запустить процесс, имеющий путь к исполняемому файлу:

Application.exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);
5 голосов
/ 23 апреля 2009

Метод запуска / выхода

// Get the parameters/arguments passed to program if any
string arguments = string.Empty;
string[] args = Environment.GetCommandLineArgs();
for (int i = 1; i < args.Length; i++) // args[0] is always exe path/filename
    arguments += args[i] + " ";

// Restart current application, with same arguments/parameters
Application.Exit();
System.Diagnostics.Process.Start(Application.ExecutablePath, arguments);

Кажется, это работает лучше, чем Application.Restart ();

Не уверен, как это происходит, если ваша программа защищает от нескольких экземпляров. Полагаю, вам лучше запустить второй .exe, который приостанавливает работу, а затем запускает для вас основное приложение.

3 голосов
/ 27 июля 2011

Попробуйте этот код:

bool appNotRestarted = true;

Этот код также должен быть в функции:

if (appNotRestarted == true) {
    appNotRestarted = false;
    Application.Restart();
    Application.ExitThread();
}
3 голосов
/ 24 июня 2016

Я нашел другое решение, возможно, любой может его использовать.

string batchContent = "/c \"@ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\"";
batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath);
Process.Start("cmd", batchContent);
Application.Exit();

Код упрощен, поэтому позаботьтесь об исключениях и прочем;)

2 голосов
/ 07 июня 2012

Я хотел, чтобы новое приложение запускалось после закрытия старого.

Использование process.WaitForExit () для ожидания завершения собственного процесса не имеет смысла. Это всегда будет время ожидания.

Итак, мой подход состоит в том, чтобы использовать Application.Exit (), затем ждать, но разрешать обработку событий в течение определенного периода времени. Затем запустите новое приложение с теми же аргументами, что и старое.

static void restartApp() {
    string commandLineArgs = getCommandLineArgs();
    string exePath = Application.ExecutablePath;
    try {
        Application.Exit();
        wait_allowingEvents( 1000 );
    } catch( ArgumentException ex ) {
        throw;
    }
    Process.Start( exePath, commandLineArgs );
}

static string getCommandLineArgs() {
    Queue<string> args = new Queue<string>( Environment.GetCommandLineArgs() );
    args.Dequeue(); // args[0] is always exe path/filename
    return string.Join( " ", args.ToArray() );
}

static void wait_allowingEvents( int durationMS ) {
    DateTime start = DateTime.Now;
    do {
        Application.DoEvents();
    } while( start.Subtract( DateTime.Now ).TotalMilliseconds > durationMS );
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...