Introdução
O artigo tem por objectivo ajudar o leitor a compreender o algoritmo base por detrás de uma aplicação auxiliar de actualização. Apenas serão expostos alguns excertos de código relevantes para uma percepção lógica do objectivo final.
A linguagem de programação escolhida para desenvolvimento não é relevante.
Notas
Sempre que haja uma referência de texto a “Aplicação Pai” esta identifica a aplicação principal da qual a aplicação auxiliar está inerente.
Factores a ter em conta
- Não é guardado nem inserido qualquer tipo de informação confidencial.
- Os processos são feitos de forma assíncrona permitindo assim uma interacção mais fluída.
- A .NET Framework utilizada neste artigo é a 3.5 pelo que deverá correr nas versões superiores sem problema.
Resultado final
O artigo dá também a conhecer ao leitor como trabalhar e aceder a diferentes threads sem comprometer a thread principal.
Algoritmo em Fluxograma
Onde disponibilizo as novas versões?
As novas versões são disponibilizadas numa pasta de FTP com permissões de acesso externas, sendo que o URL neste artigo descrito encontra-se sobre o meu servidor pessoal para usos didácticos.
Como informei anteriormente não é necessário guardar qualquer informação confidencial, o URL é suficiente.
private static string url = "http://stuffpinho.com/portugal-a-programar/revista/artigos/updater/";
Qual a formatação do ficheiro de actualização?
A formatação fica ao critério do leitor sendo necessário, à posterior, a adaptação do código para interpretação dessa mesma formatação.
1.0.3 Nomeficheiro.exe Nomeficheiro.dll Etc
Sendo a primeira linha a identificação da versão mais recente e as restantes linhas identificam quais os ficheiros que devem ser transferidos.
Comparação da versão actual com a mais recente
O primeiro objectivo da aplicação, que deve ser interpretado como decisivo, é validar a versão actual da Aplicação Pai que, por norma, se encontra no mesmo sítio da aplicação auxiliar de actualização.
private static string path = Path.GetDirectoryName(Application.ExecutablePath); // Input: 1.0.3.0 string version = FileVersionInfo.GetVersionInfo(path + "\\PAP.exe").ProductVersion; // Input desejado: 1.0.3 (neste artigo) currentVersion = version.Remove(version.Length - 2);
FileVersionInfo
encontra-se sobre o namespace System.Diagnostics
e permite-nos ter acesso directo às informações de um ficheiro, seja a versão do mesmo; direitos de autor; empresa de desenvolvimento; etc.
Para identificarmos a versão mais recente é necessário transferir o ficheiro denominado (no meu caso) update.txt
, bem como ler a estrutura do mesmo.
Para transferência de ficheiros externos dá-se uso ao namespace System.Net
que nos permite para além de receber ficheiros, enviar.
WebClient webClient = new WebClient(); webClient.DownloadFileCompleted += (object sender, AsyncCompletedEventArgs e) => { latestVersion = getLatestVersion(); if (latestVersion == currentVersion) { /* * A aplicação encontra-se actualizada. * 1. Eliminamos o ficheiro 'Update.txt'; * 2. Executamos novamente a Aplicação Pai; * 3. Fechamos a aplicação auxiliar; */ return; } downloadFiles(); }; webClient.DownloadFileAsync(new Uri(url + "update.txt"), path + "\\update.txt");
Transferir os ficheiros da versão mais recente
O método downloadFiles()
transfere os ficheiros necessários a bom funcionamento da nova versão.
Mas antes de transferir é necessário ler (do ficheiro .txt
transferido anteriormente) quais os ficheiros disponibilizados e necessários.
private string[] getAllFilesToDownload() { return File.ReadAllLines(path + "\\update.txt"); } private void downloadFiles() { // Retorna todas as linhas do ficheiro .txt inclusive a versão. string[] files = getAllFilesToDownload(); bool stop = true; foreach (string file in files) { /* * Visto que a primeira linha é a versão da aplicação, não * existe nenhum ficheiro para ser transferido, portanto * ignora-se a linha. * A solução passa por criar a variável booleana `stop` ou * se o leitor preferir, eliminar a primeira linha. */ if (stop == true) { stop = false; continue; } WebClient webClient = new WebClient(); /* * Exemplo de output final: * (Download) url + file = “../updater/nomeFicheiro.dll” * (DownloadTo) path + file = “C:\pasta\nomeFicheiro.dll” */ webClient.DownloadFileAsync(new Uri(url + file), path + "\\" + file); /* * O download é feito através da função DownloadFileAsync() * o que implica que, se houverem múltiplos ficheiros a * serem transferidos ao mesmo tempo, poderá causar * uma abrupta falha na aplicação. O ideal será então * verificar, dentro do ciclo, se a transferência * encontra-se concluída e só aí passar para a próxima * linha. * * Se o leitor prefeir pode utilizar uma variável * auxiliar em vez de verificar o valor da progressbar */ while (this.progress_bar.Value != 100) { Application.DoEvents(); } } /* * A aplicação encontra-se actualizada. * 1. Eliminamos o ficheiro ‘Update.txt’; * 2. Executamos novamente a Aplicação Pai; * 3. Fechamos a aplicação auxiliar; * 4. A aplicação está oficialmente actualizada! */ }
Conclusão
Em suma, a aplicação auxiliar é parte integral da Aplicação Pai que possibilita ao cliente final estar sempre a par das actualizações de forma mais rápida e objectiva.