Как перезапустить приложение c# WinForm?
20 ответов
к сожалению, вы не можете использовать Process.Метод start() для запуска экземпляра процесса. Согласно процессу.Start () docs: "Если процесс уже запущен, дополнительный ресурс процесса не запускается..."
этот метод будет отлично работать под отладчиком VS (потому что VS делает какую-то магию, которая вызывает процесс.Начните думать, что процесс еще не запущен), но произойдет сбой, если он не будет запущен под отладчиком. (Обратите внимание, что это может быть OS-specific-I кажется, помните, что в некоторых моих тестах он работал либо на XP, либо на Vista, но я могу просто вспомнить его запуск под отладчиком.)
этот метод именно тот, который использовался последним программистом в проекте, над которым я сейчас работаю, и я пытался найти обходной путь для этого в течение некоторого времени. До сих пор я нашел только одно решение, и оно просто кажется мне грязным и kludgy: запустите 2-е приложение, которое ждет в фоновом режиме для первого приложения чтобы завершить, затем повторно запускает 1-е приложение. Я уверен, что это сработает, но, тьфу.
Edit: использование 2-го приложения работает. Все, что я сделал во втором приложении было:
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, "");
}
(Это очень упрощенный пример. Реальный код имеет много проверки здравомыслия, обработки ошибок и т. д.)
Если вы находитесь в основной форме приложения, попробуйте использовать
System.Diagnostics.Process.Start( Application.ExecutablePath); // to start new instance of application
this.Close(); //to turn off current app
гораздо более простой подход, который работал для меня:
Application.Restart();
Environment.Exit(0);
это сохраняет аргументы командной строки и работает, несмотря на обработчики событий, которые обычно предотвращают закрытие приложения.
вызов Restart () пытается выйти, запускает новый экземпляр в любом случае и возвращает. Затем вызов Exit () завершает процесс, не давая возможности запустить обработчикам событий. Существует очень короткий период, в течение которого оба процесса работают, что не является проблемой в мое дело, но, возможно, в других случаях.
код выхода 0 в Environment.Exit(0);
указывает чистое завершение работы. Вы также можете выйти с 1, чтобы указать произошла ошибка.
Я могу опоздать на вечеринку, но вот мое простое решение, и оно работает как шарм с каждым приложением, которое у меня есть:
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
{ }
у меня была такая же точная проблема, и у меня тоже было требование предотвратить дублирование экземпляров - я предлагаю альтернативное решение тому, что предлагает HiredMind (что будет работать нормально).
то, что я делаю, это запуск нового процесса с processId старого процесса (тот, который запускает перезапуск) в качестве аргумента строки 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 args и проверяю, есть ли флаг перезапуска с 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
}
}
Я, очевидно,не показываю все проверки безопасности, которые у меня есть на месте и т. д.
даже если не идеально - я считаю это допустимой альтернативой, так что вам не нужно иметь на месте отдельное приложение только для обработки перезагрузки.
его просто вам просто нужно позвонить Application.Restart()
методы, которые имеют тенденцию вызывать приложение для перезапуска. Но вы должны выйти из локальной среды со своими кодами ошибок:
Application.Restart();
Environment.exit(int errorcode);
вы можете создать перечисление кодов ошибок, которые вы можете использовать его эффективно.
другой метод - просто выйти из приложения и запустить процесс, имеющий исполняемый путь:
Application.exit();
System.Diagnostics.Process.Start(Application.ExecutablePath);
Метод Запуска / Выхода
// 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);
Это, кажется, работает лучше, чем приложение.Restart();
не уверен, как это работает, если ваша программа защищает от нескольких экземпляров. Я думаю, тебе лучше начать со второго .exe, который приостанавливается, а затем запускает ваше основное приложение для вас.
попробуйте этот код:
bool appNotRestarted = true;
этот код должен быть в функции:
if (appNotRestarted == true) {
appNotRestarted = false;
Application.Restart();
Application.ExitThread();
}
Я придумал другое решение, возможно, любой может его использовать.
string batchContent = "/c \"@ECHO OFF & timeout /t 6 > nul & start \"\" \"$[APPPATH]$\" & exit\"";
batchContent = batchContent.Replace("$[APPPATH]$", Application.ExecutablePath);
Process.Start("cmd", batchContent);
Application.Exit();
код упрощен, поэтому позаботьтесь об исключениях и прочее;)
вы забываете параметры/параметры командной строки, которые были переданы вашему текущему экземпляру. Если вы не передадите их, вы не будете делать настоящий перезапуск. Установите Process.StartInfo
с клоном параметров вашего процесса, затем выполните запуск.
например, если процесс был запущен как myexe -f -nosplash myfile.txt
, ваш метод будет выполняться только myexe
без всех этих флагов и параметров.
Я хотел, чтобы новое приложение запустилось после завершения работы старого.
через процесса.WaitForExit () ждать завершения собственного процесса не имеет смысла. Это всегда будет тайм-аут.
Итак, мой подход заключается в использовании приложения.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 );
}
вы также можете использовать Рестартеры.
Restarter-это приложение, которое автоматически контролирует и перезапускает разбитые или зависшие программы и приложения. Первоначально он был разработан для мониторинга и перезапуска игровых серверов, но он будет выполнять работу для любой консоли или формы на основе программы или приложения
public static void appReloader()
{
//Start a new instance of the current program
Process.Start(Application.ExecutablePath);
//close the current application process
Process.GetCurrentProcess().Kill();
}
приложение.ExecutablePath возвращает свое применение .путь к файлу exe Пожалуйста, следуйте порядку звонков. Вы можете поместить его в предложение try-catch.
вот мои 2 цента:
последовательность запуска нового экземпляра - >закрыть текущий экземпляр должен работать даже для приложений, которые не позволяют запускать несколько копий одновременно, так как в этом случае новый экземпляр может быть передан аргумент командной строки, который будет указывать, что происходит перезапуск, поэтому проверка других запущенных экземпляров не потребуется. Ожидание первого экземпляра, чтобы на самом деле закончить мою реализацию тоже, если это абсолютно необходимо, чтобы нет два intstances работают параллельно.
Я боюсь, что перезапуск всего приложения с помощью процесса приближается к вашей проблеме неправильно.
более простой способ-изменить программу.cs файл для перезапуска:
static bool restart = true; // A variable that is accessible from program
static int restartCount = 0; // Count the number of restarts
static int maxRestarts = 3; // Maximum restarts before quitting the program
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
while (restart && restartCount < maxRestarts)
{
restart = false; // if you like.. the program can set it to true again
restartCount++; // mark another restart,
// if you want to limit the number of restarts
// this is useful if your program is crashing on
// startup and cannot close normally as it will avoid
// a potential infinite loop
try {
Application.Run(new YourMainForm());
}
catch { // Application has crashed
restart = true;
}
}
}
у меня была аналогичная проблема, но моя была связана с неуправляемой утечкой памяти, которую я не мог найти в приложении, которое должно работать 24/7. С клиентом я согласился, что безопасное время для перезапуска приложения было 03: 00AM, если потребление памяти превышало определенное значение.
пробовал Application.Restart
, но поскольку он, похоже, использует какой-то механизм, который запускает новый экземпляр, пока он уже запущен, я пошел на другую схему. Я использовал трюк, который обрабатывает файловая система, до тех пор, пока процесс создал их умирает. Итак, из приложения я уронил файл на диск и не сделал Dispose()
ручки. Я использовал файл для отправки исполняемого файла "себя" и запуска каталога (чтобы добавить гибкость).
код:
_restartInProgress = true;
string dropFilename = Path.Combine(Application.StartupPath, "restart.dat");
StreamWriter sw = new StreamWriter(new FileStream(dropFilename, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite));
sw.WriteLine(Application.ExecutablePath);
sw.WriteLine(Application.StartupPath);
sw.Flush();
Process.Start(new ProcessStartInfo
{
FileName = Path.Combine(Application.StartupPath, "VideoPhill.Restarter.exe"),
WorkingDirectory = Application.StartupPath,
Arguments = string.Format("\"{0}\"", dropFilename)
});
Close();
Close()
в конце будет инициировать завершение работы приложения и дескриптор файла, который я использовал для StreamWriter
здесь будет открыто до тех пор, пока процесс действительно не умрет. Затем...
Рестартеры.exe вступает в действие. Он пытается прочитать файл в эксклюзивном режиме, предотвращение доступа, пока основное приложение не было мертвым, затем запускает основное приложение, удаляет файл и существует. Я думаю, что это не может быть проще:
static void Main(string[] args)
{
string filename = args[0];
DateTime start = DateTime.Now;
bool done = false;
while ((DateTime.Now - start).TotalSeconds < 30 && !done)
{
try
{
StreamReader sr = new StreamReader(new FileStream(filename, FileMode.Open, FileAccess.ReadWrite, FileShare.ReadWrite));
string[] runData = new string[2];
runData[0] = sr.ReadLine();
runData[1] = sr.ReadLine();
Thread.Sleep(1000);
Process.Start(new ProcessStartInfo { FileName = runData[0], WorkingDirectory = runData[1] });
sr.Dispose();
File.Delete(filename);
done = true;
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Thread.Sleep(1000);
}
}
Как насчет создания файла bat, запустите пакетный файл перед закрытием, а затем закройте текущий экземпляр.
пакетный файл делает следующее:
- подождите в цикле, чтобы проверить, вышел ли процесс.
- запустить процесс.
Я использую следующее, И он делает именно то, что вы ищете:
ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;
UpdateCheckInfo info = null;
info = ad.CheckForDetailedUpdate();
if (info.IsUpdateRequired)
{
ad.UpdateAsync(); // I like the update dialog
MessageBox.Show("Application was upgraded and will now restart.");
Environment.Exit(0);
}
для использования в качестве выхода из системы вам необходимо завершить все приложения из кэша Ram поэтому сначала закройте приложение, а затем повторите его
//при нажатии кнопки "Выход"
foreach(Form frm in Application.OpenForms.Cast<Form>().ToList())
{
frm.Close();
}
System.Diagnostics.Process.Start(Application.ExecutablePath);
проблема использования приложение.Restart () заключается в том, что он запускает новый процесс, но "старый" все еще остается. Поэтому я решил убить старый процесс, используя следующий фрагмент кода:
if(Condition){
Application.Restart();
Process.GetCurrentProcess().Kill();
}
и он работает хорошо. В моем случае MATLAB и приложение C# используют одну и ту же базу данных SQLite. Если MATLAB использует базу данных, форма-приложение должно перезапустить (+обратный отсчет) снова, пока MATLAB не сбросит бит занятости в базе данных. (Только для стороны информация)