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.

Foi útil?

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top