Terminate a process in C # with WPF

4

I have a solution that has two projects. one main project and one that serves as an Updater.

To perform the upgrade, within the main project, I call a console application as follows.

private void Window_Loaded(object sender, RoutedEventArgs e)
    {

        //Lê arquivo xml e manipula arquivo xml
        XmlDocument doc = new XmlDocument();
        doc.Load("http://www.meusite.org.br/Cantina/arquivoXML.xml");
        XmlNode node = doc.DocumentElement.SelectSingleNode("/Application/Version");
        XmlNode node1 = doc.DocumentElement.SelectSingleNode("/Application/ZipFile");
        string version = node.InnerText;
        string zipfile = node1.InnerText;
        string End = (@"\aps-serverweb\wwwroot\meusite.org.br\Cantina\");
        string file = (End + zipfile);
        string versionAssembly = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

        //valida version (versão disponível no servidor para atualização) e versionAssembly (versão do sistema isntalado) 
        if (Convert.ToDouble(version) <= Convert.ToDouble(versionAssembly))
        {
           // MessageBox.Show("Sistema Atualizado" + version); 
        }
        else
        {
            //chama o projeto de atualiação de sistema console application IASD.ASCS.Updater
            Process myProc = Process.Start("Updater.exe");

        }
}

When calling the Updater (console application) process, the following code is executed.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
using Ionic.Zip;
using System.Xml;
using System;
using System.IO;
using Microsoft.VisualBasic;
using System.Threading;

namespace Updater
{
    class Program
    {
    static void Main(string[] args)
    {
        string nomeExecutavel = "IASD.ASCS.WPF.exe";
        foreach (Process pr in Process.GetProcessesByName(nomeExecutavel))
        {
            if (!pr.HasExited) pr.Kill();
        }

        //Lê e manipula arquivo xml com as informações do arquivo zip contendo a atualização disponível
        XmlDocument doc = new XmlDocument();
        doc.Load("http://www.meusite.org.br/Cantina/arquivoXML.xml");
        XmlNode node = doc.DocumentElement.SelectSingleNode("/Application/Version");
        XmlNode node1 = doc.DocumentElement.SelectSingleNode("/Application/ZipFile");
        string version = node.InnerText;
        string zipfile = node1.InnerText;
        string End = (@"\aps-serverweb\wwwroot\meusite.org.br\Cantina\");
        string file = (End + zipfile);
        string versionAssembly = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();

        //Utiliza os métodos da biblioteca dotnetzip chamada Ionic.zip para baixar e extrair arquivos zip
        ZipFile zipFile = ZipFile.Read(file);
        {
            foreach (ZipEntry zipEntry in zipFile)
            {
                zipEntry.Extract(@"C:\IASD\CantinaEscolar\Temp\", ExtractExistingFileAction.OverwriteSilently);
            }
        }

        foreach (Process pr in Process.GetProcessesByName(nomeExecutavel))
        {
            if (!pr.HasExited) pr.Kill();
        }

        //Transfere os arquivos baixados no diretório Temp para o diretório instalação em c:\IASD\CantinaEscolar 
        string dirTemp = @"c:\IASD\CantinaEscolar\Temp";
        string dirInstalacao = @"c:\IASD\CantinaEscolar";
        string[] arquivos = Directory.GetFiles(dirTemp);
        foreach (string item in arquivos)
        {
            string nomedoarquivo = Path.GetFileName(item);
            string destino = Path.Combine(dirInstalacao, nomedoarquivo);
            File.Copy(item, destino, true);
        }
        string[] arquivosApagar = Directory.GetFiles(dirTemp);
        foreach (string item in arquivosApagar)
        {
            File.Delete(item);
        }

        foreach (Process pr in Process.GetProcessesByName(nomeExecutavel))
        {
            if (!pr.HasExited) pr.Start();
        }

        //Encerra o processo Updater
        string nomeExecutavel2 = "Updater.exe";
        foreach (Process pr2 in Process.GetProcessesByName(nomeExecutavel2))
           {
            if (!pr2.HasExited) pr2.Kill();
           }
       }
   }
}

The updater basically does the following

  • Terminates the main process

  • Checks if you have an update available in the directory through an xml file. (this is also done in the main process to enter the Updater).

  • Unpack to a temporary folder.

  • Copy to the main project installation folder.

  • Deletes files from the c:\IASD\CantinaEscolar\Temp directory

  • This works flawlessly running within visual studio.

    Now when installing the application on a computer, at the time of copying the 'update' files from the Temp folder to the installation directory, an error is returned stating that the file is running.

    The process that needs to be terminated when I'm running the application in Visual Studio is called IASD.ASCS.WPF.vshost . When the application is installed, the process changes name, becoming IASD.ASCS.WPF.exe which is the name of the project inside the solution as well as the name of its executable that is in the bin\Debug folder.

    I tried to end this process in the following ways and did not succeed:

    String nome = "IASD.ASCS.WPF.exe";
            // Obtém lista de processos
            Process[] processos = Process.GetProcesses();
    
            foreach (Process p in processos)
            {
                if (p.ProcessName.ToUpper() == nome.ToUpper())
                {
                    // Tenta fechar a janela principal,
                    // se falhar invoca o método Kill()
                    if (!p.CloseMainWindow())
                    {
                        p.Kill();
                    }
                    p.Close(); // Libera recursos associados.
                }
            }
    
    
            Process[] processes = Process.GetProcessesByName("Login.exe");
    
            foreach (Process process in processes)
            {
                process.Kill();
            }
    
            Process[] processes1 = Process.GetProcessesByName("Login");
    
            foreach (Process process1 in processes1)
            {
                process1.Kill();
            }
    
            Process[] processes2 = Process.GetProcessesByName("IASD.ASCS.WPF.exe");
    
            foreach (Process process2 in processes2)
            {
                process2.Kill();
            }
    
            Process[] processes3 = Process.GetProcessesByName("IASD.ASCS.WPF");
    
            foreach (Process process3 in processes3)
            {
                process3.Kill();
            }
    
            Process[] processes4 = Process.GetProcessesByName("vshost32");
    
            foreach (Process process4 in processes4)
            {
                process4.Kill();
            }
    
            Process[] processes5 = Process.GetProcessesByName("vshost32.exe");
    
            foreach (Process process5 in processes5)
            {
                process5.Kill();
            }
    

    None of them work when the application is installed.

    Note: The Login process mentioned in the code is the name of the WPF created according to the image of the Windows task manager:

    How could I close the IASD.ASCS.WPF.exe process so that the application console will copy the files from the temp folder to the application's installation folder and then restart this process?

        
    asked by anonymous 08.04.2014 / 14:27

    2 answers

    4

    Is there a way to close it before calling the Updater?

    // verifica se existe uma atualização
    // e se existir, inicia o Updater.exe e depois se fecha
    if (existeUmaAtualizacao)
    {
        Process myProc = Process.Start("Updater.exe");
        Application.Current.Shutdown();
    }
    

    Within the Updater, it may be necessary to attempt to delete the original executable file, within a loop, until, with a timeout obviously, the Updater may crash:

    var timeout = DateTime.Now + TimeSpan.FromSeconds(30);
    while (DateTime.Now < timeout)
    {
        try
        {
            File.Delete("IASD.ASCS.WPF.exe");
            break;
        }
        catch { }
    }
    
    if (!File.Exists("IASD.ASCS.WPF.exe"))
    {
        // arquivo foi excluido com sucesso,
        // agora podemos copiar o arquivo atualizado que está na pasta TEMP
    }
    
        
    08.04.2014 / 15:02
    1

    WARNING: Although I have already used / tested all these techniques, I have never built any applications as I will describe here.

    The IASD.ASCS.WPF.vshost.exe executable is the Visual Studio hosting process > for this project. The function of this executable is to streamline the process of debugging the applications avoiding the need to create a new process each time the application runs.

    I'm not sure, but I assume that with each run that the executables have been modified, a new application domain to load the executables and run them. In order for the executables to be modified even with the program running, I assume that the application domain is created with # - the same process as ASP.NET uses.

    If you instead have a updater you have a controller that launches your application into a separate application domain with shadow copy application and update. If an update has been made, the current application domain is terminated and a new one with a minimal downtime is created. If there is a requirement to keep the application running, the same mechanism can be used to re-launch the application whenever the application domain terminates unexpectedly.     

    09.04.2014 / 12:59