Почему Application.Restart() не является надежным?

Использование метода Application.Restart() в С# должно перезапустить текущее приложение: но кажется, что это не всегда работает.

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

Ответ 1

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

  • Закрытие события в форме может остановить остановку приложения.
  • Если вы выполняете проверку уже запущенного процесса, старый может не закрываться достаточно быстро, чтобы новый запускался.

Проверьте свой код для таких ошибок. Если вы видите это поведение в пустом приложении, то это скорее будет проблемой с фактической функцией, чем ваш код.

Ответ 2

В моем случае (NO single-instance), где

Application.Restart();

не работает,

System.Diagnostics.Process.Start(Application.ExecutablePath);
Application.Exit();

выполнил задание!

Ответ 3

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

EDIT:

Теперь я столкнулся с другим экземпляром и, основываясь на ваших комментариях, он, возможно, отражает то, что вы испытывали.

При запуске приложения с одним экземпляром, используя Mutex, я вызывал Application.Restart() из довольно встроенного местоположения, для которого было много очистки. Таким образом, кажется, что перезагрузка запускает новый экземпляр до того, как предыдущий экземпляр был завершен, поэтому Mutex не запускал новый экземпляр.

Ответ 4

В моей программе у меня есть мьютекс, чтобы обеспечить только один экземпляр приложения, запущенного на компьютере. Это привело к тому, что вновь запущенное приложение не запускалось, потому что мьютекс не был выпущен своевременно. В результате я поместил значение в Properties.Settings, что указывает на перезапуск приложения. Перед вызовом Application.Restart() значение Properties.Settings установлено на true. В Program.Main() я также добавил проверку для этого конкретного значения property.settings, чтобы при true оно reset false, и есть Thread.Sleep(3000);

В вашей программе у вас может быть логика:

if (ShouldRestartApp)
{
   Properties.Settings.Default.IsRestarting = true;
   Properties.Settings.Default.Save();
   Application.Restart();
}

В Program.Main()

[STAThread]
static void Main()
{
   Mutex runOnce = null;

   if (Properties.Settings.Default.IsRestarting)
   {
      Properties.Settings.Default.IsRestarting = false;
      Properties.Settings.Default.Save();
      Thread.Sleep(3000);
   }

   try
   {
      runOnce = new Mutex(true, "SOME_MUTEX_NAME");

      if (runOnce.WaitOne(TimeSpan.Zero))
      {
         Application.EnableVisualStyles();
         Application.SetCompatibleTextRenderingDefault(false);
         Application.Run(new Form1());
      }
   }
   finally
   {
      if (null != runOnce)
         runOnce.Close();
   }
}

Что это.

Ответ 5

Попробуйте блокировку перед сбросом. Вот как я запускаю полный спуск приложений. Может работать для вас, может и нет.

Context.Application.Lock();
Context.Session.Abandon();
Context.Application.RemoveAll();
Context.Application.Restart();
Context.Application.UnLock();

Ответ 6

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

Ответ 7

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

bool appNotRestarted = true;

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

if (appNotRestarted == true)
{
    appNotRestarted = false;
    Application.Restart();
    Application.ExitThread();
}

Ответ 8

Application.Restart();
Application.ExitThread();                                                     

это сработало для меня спасибо.

Ответ 9

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

Мне понадобилось решение, которое инициировало бы последовательность обновления во время запуска приложения ClickOnce из кода. Applicatoin.Restart этого не делал. Я хотел получить возможность проверить обновление, а затем вызвать встроенный менеджер обновлений, чтобы мне не пришлось писать пользовательский.

    'VB Code Sample
    Dim strStart As String = System.Environment.GetFolderPath(Environment.SpecialFolder.StartMenu) & "\Programs\Folder\YourApplication.appref-ms"
    Application.Exit()
    Try
        Process.Start(strStart)
    Catch ex As Exception
        'Do something with the exception
    End Try

Единственная проблема, с которой я сталкиваюсь с этим обходным путем, заключается в том, что пользователь может удалить ярлык из меню "Пуск". Если это вызывает беспокойство, вы можете написать какой-то код, чтобы скопировать ссылку меню "Пуск" в выбранную вами папку, желательно в папке приложения ClickOnce. Это важно, потому что значок меню запуска для вашего приложения не является .lnk или .exe, это фактически ссылка .appref-ms. См. ClickOnce.appref-ms больше, чем ссылка на файл .application? Эта ссылка объясняет это более подробно.

Этот код будет работать с приложениями ClickOnce SingleInstance.

Ответ 10

public static void ApplicationRestart(params string[] commandLine)
    {
        lock (SynchObj)
        {
            if (Assembly.GetEntryAssembly() == null)
            {
                throw new NotSupportedException("RestartNotSupported");
            }

            if (_exiting)
                return;

            _exiting = true;

            if (Environment.OSVersion.Version.Major < 6) return;

            bool cancelExit = true;

            try
            {
                foreach (Form f in Application.OpenForms.OfType<Form>().ToList())
                {
                    f.InvokeIfRequired(frm =>
                    {
                        frm.FormClosing += (sender, args) => cancelExit = args.Cancel;
                        frm.Close();
                    });

                    if (cancelExit) break;
                }

                if (cancelExit) return;

                Process.Start(new ProcessStartInfo
                {
                    UseShellExecute = true,
                    WorkingDirectory = Environment.CurrentDirectory,
                    FileName = Application.ExecutablePath,
                    Arguments = commandLine.Length > 0 ? string.Join(" ", commandLine) : string.Empty
                });

                Application.Exit();
            }
            finally
            {
                _exiting = false;
            }
        }
    }