Como agendar um processo.start no wpf
-
27-09-2019 - |
Pergunta
Estou tentando reiniciar um aplicativo no WPF.
Eu tentei o seguinte:
Process.Start(Application.ExecutablePath);
Process.GetCurrentProcess().Kill();
E não funciona porque o aplicativo é configurado como um único aplicativo de instâncias.
Então eu cansei isto:
Process.GetCurrentProcess().Kill();
Process.Start(Application.ExecutablePath);
E não funciona porque, uma vez que matamos o processo, ele não atingirá a linha 2
Existe uma maneira de agendar um .start para que eu não encontre a edição 1.
Solução
Você pode iniciar um aplicativo secundário que relançaria seu programa principal após o atraso. Quando escrevi um auto-dador, alguns anos atrás, esse foi o caminho de implementação que eu segui. Era apenas um programa simples que tomou o executável como uma linha de comando Arg, dormia por um décimo de segundo e depois o iniciava.
Um melhor caminho de implementação do que eu levei seria que o programa recém-lançado aguarde o processo que o lançou para terminar. Esperar o período arbitrário pode complicar as questões. Para conseguir isso, eu provavelmente passaria o ID do processo para o relançamento, para que soubesse exatamente em qual processo esperar.
Outras dicas
Não é tão difícil quanto você pensa. Tudo o que você precisa fazer é chamar o seguinte método, passando na linha de comando para a instância reiniciada:
public static void RestartMe(string commandLine)
{
var myId = Process.GetCurrentProcess().Id;
var myPath = Assembly.GetEntryAssembly().CodeBase.Replace("file:///", "");
var systemPath = typeof(object).Assembly.CodeBase.Replace("file:///", "");
var tempPath = Path.GetTempFileName();
File.WriteAllText(tempPath + ".cs", @"
using System;
using System.Diagnostics;
public class App
{
public static void Main(string[] args)
{
try { Process.GetProcessById(" + myId + @").WaitForExit(); } catch {}
Process.Start(""" + myPath + @""", Environment.CommandLine);
}
}");
var compiler = new ProcessStartInfo
{
FileName = Path.Combine(Path.GetDirectoryName(systemPath), "csc.exe"),
Arguments = tempPath + ".cs",
WorkingDirectory = Path.GetDirectoryName(tempPath),
WindowStyle = ProcessWindowStyle.Hidden,
};
var restarter = new ProcessStartInfo
{
FileName = tempPath + ".exe",
Arguments = commandLine,
WindowStyle = ProcessWindowStyle.Hidden,
};
Process.Start(compiler).WaitForExit();
Process.Start(restarter); // No WaitForExit: restarter WaitForExits us instead
File.Delete(tempPath);
File.Delete(tempPath + ".cs");
Environment.Exit(0);
}
Como funciona: na verdade, isso cria outro programa "restaurador", mas o faz de maneira indolor e automática. O Programa Restarter possui o ID do processo atual e o nome do arquivo executável incorporado diretamente nele. Ele sempre encontrará o compilador porque a versão da estrutura da rede é fornecida com um csc.exe compatível na mesma pasta que o System.dll.