André Alves de Lima

Talking about Software Development and more…

Como atualizar aplicações .NET automaticamente?

Um grande desafio que temos ao desenvolvermos aplicações desktop é a questão da atualização para novas versões. Diferentemente de aplicações web, onde o usuário sempre receberá a versão mais atual que estiver disponibilizada no servidor, com as aplicações desktop nós temos que implementar essa atualização de forma manual. Para isso, nós temos à nossa disposição algumas ferramentas que nos ajudarão a atualizar as nossas aplicações .NET automaticamente quando uma nova versão estiver disponível. No artigo de hoje eu vou mostrar para você 3 ferramentas que implementam essa funcionalidade.

Aplicação de exemplo

Você pode utilizar qualquer aplicação desktop para testar as funcionalidades que serão apresentadas neste artigo. Isso quer dizer que o seu projeto pode ser do tipo Console Application, Windows Forms ou WPF, independente da linguagem (C# ou VB.NET).

Para simplificar as coisas, a aplicação que testaremos no artigo será do tipo Console Application. Ela será uma aplicação extremamente simples, que só mostra o nome e a versão do assembly no console:

        // C#
        static void Main(string[] args)
        {
            var assembly = System.Reflection.Assembly.GetExecutingAssembly();
            var titleAttribute = assembly.GetCustomAttributes(typeof(System.Reflection.AssemblyTitleAttribute), false).FirstOrDefault() as System.Reflection.AssemblyTitleAttribute;
            var title = titleAttribute?.Title;
            var version = assembly.GetName().Version.ToString();
            Console.WriteLine(string.Format("Assembly Title: {0}", title));
            Console.WriteLine(string.Format("Assembly Version: {0}", version));
            Console.ReadLine();
        }
    ' VB.NET
    Sub Main()
        Dim Assembly = System.Reflection.Assembly.GetExecutingAssembly()
        Dim TitleAttribute = TryCast(Assembly.GetCustomAttributes(GetType(System.Reflection.AssemblyTitleAttribute), False).FirstOrDefault(), System.Reflection.AssemblyTitleAttribute)
        Dim Title = If(TitleAttribute IsNot Nothing, TitleAttribute.Title, String.Empty)
        Dim Version = Assembly.GetName().Version.ToString()
        Console.WriteLine(String.Format("Assembly Title: {0}", Title))
        Console.WriteLine(String.Format("Assembly Version: {0}", Version))
        Console.ReadLine()
    End Sub

Você consegue encontrar as informações de versão do assembly nas propriedades do projeto, aba “Application“, botão “Assembly Information“:

A propósito, os números de versão do assembly e do arquivo são informações extremamente importantes quando trabalhamos com instaladores e atualizadores, uma vez que ela pode ser a base da decisão se uma atualização está disponível ou não. Caso você não saiba, eu já publiquei um artigo uns tempos atrás mostrando como gerenciar números de versão em projetos .NET. O código apresentado acima é uma versão simplificada do código elaborado no artigo sobre números de versão.

Opção 1: ClickOnce

O ClickOnce é a ferramenta da própria Microsoft que implementa a funcionalidade de instalação e atualização de aplicações desktop. Ela está disponível no Visual Studio desde a versão 2005, quando o .NET Framework 2.0 foi lançado. Todas as opções do ClickOnce estão disponíveis nas propriedades do projeto, mais especificamente na aba “Publish“:

Nota: se a sua solução tiver mais de um projeto, você terá que fazer as configurações no projeto que é o “entry point” da sua aplicação, ou seja, no executável.

Dentro da aba “Publish“, nós conseguiremos fazer algumas configurações mais específicas através destes quatro botões:

No botão “Application Files“, nós podemos selecionar quais serão os arquivos que deverão ser copiados para a pasta de instalação do aplicativo. O Visual Studio costuma fazer um excelente trabalho detectando quais arquivos devem ser incluídos ou não (utilizando as referências dos projetos, itens que estão marcados como “Copy to output directory“, etc). Porém, caso você tenha algum arquivo adicional (como um arquivo de backup do SQL Server que você restaurará automaticamente na primeira execução, como demonstrei neste outro artigo), você terá que adicioná-lo nessa janela.

Já na janela de “Prerequisites” nós conseguimos, como o próprio nome já diz, selecionar pré-requisitos adicionais que serão instalados juntamente com a aplicação. Por exemplo, você pode selecionar o SQL Server Express (ou LocalDB) como pré-requisito, dessa forma uma instância será instalada e habilitada automaticamente quando o usuário fizer a instalação da nossa aplicação.

Na parte de “Updates” nós temos uma configuração muito importante, que é a questão de atualizações da nossa aplicação. A grande vantagem que temos ao fazer a instalação pelo ClickOnce é justamente a opção de manter a aplicação atualizada automaticamente:

Como você pode ver, nessa janela nós conseguimos ativar ou desativar as atualizações automáticas. Além disso, nós podemos definir se o ClickOnce fará a checagem de atualizações antes ou depois da inicialização da aplicação, além de uma versão mínima e um endereço customizado onde as atualizações serão disponibilizadas.

Por fim, temos um último botão chamado “Options“, onde encontraremos configurações gerais da publicação. Por exemplo, se quisermos adicionar a criação de um ícone no desktop para a nossa aplicação, nós temos que marcar a seguinte opção:

Nessa mesma aba “Publish“, nós temos o número da versão de publicação:

Não confunda o número da versão do assembly / arquivo (que expliquei anteriormente) com a versão da publicação. Esses números são independentes e podem ter versões completamente distintas para cada um deles. Caso você queira acessar o número da versão da publicação em tempo de execução, você terá que utilizar as informações disponíveis na classe System.Deployment.Application.ApplicationDeployment.CurrentDeployment, conforme demonstrado nesta thread do StackOverflow.

Uma vez realizadas as configurações básicas, nós vamos utilizar o “Publish Wizard” para especificarmos os locais de publicação. O ClickOnce pode funcionar simplesmente como um instalador comum (sem checagem de atualizações), porém, caso você só queira criar um instalador sem suporte a atualizações, eu recomendo que você utilize uma outra ferramenta de instalador mais robusta (como o InnoSetup ou até mesmo os projetos de instalador do Visual Studio, ambos apresentados neste outro artigo que eu publiquei uns tempos atrás).

Para trabalhar com atualizações automáticas no ClickOnce, nós teremos que disponibilizar as atualizações em um site no IIS ou em um caminho na rede. Seria excelente se o ClickOnce permitisse a publicação em um caminho em disco, uma vez que isso facilitaria bastante os testes, mas infelizmente isso não é possível. Se tentarmos especificar um caminho em disco para a atualização, nós receberemos uns erros estranhos, como estes:

Porém, uma gambiarra que podemos empregar para testarmos o deployment local é utilizarmos um caminho no formato UNC em conjunto com o compartilhamento de disco padrão do Windows (C$, D$, etc). No tutorial deste artigo nós trabalharemos com essa alternativa.

Na primeira página do “Publish Wizard“, nós temos que indicar o caminho onde a aplicação será publicada. Se estivéssemos fazendo um deployment “de verdade“, nós provavelmente indicaríamos nessa etapa o caminho do FTP (ou caminho da rede) onde a aplicação está publicada no IIS. Porém, para testarmos o deployment local, nós deixaremos o caminho como “publish\” (que é o padrão):

Em seguida, na próxima etapa do assistente nós temos que indicar o local por onde o usuário vai instalar a nossa aplicação. Uma opção é através de CD (não recomendado – como já mencionei anteriormente, vale muito mais a pena utilizar um instalador mais robusto para esse cenário). Caso estivéssemos publicando a nossa aplicação no IIS, nesta etapa nós teríamos que indicar a URL pública do IIS (ou da intranet, se a aplicação fosse interna). Porém, como nós estamos tentando testar um deployment local, nós indicaremos um caminho UNC apontando para a mesma pasta “publish“:

Nota: no meu caso, o caminho UNC ficou assim: “\\192.168.178.20\C$\Users\jamje\Documents\Visual Studio 2015\Projects\AtualizadorAplicacao\AtualizadorAplicacao\publish\”. Obviamente, no seu caso você precisará substituir o IP e o caminho de forma que eles correspondam à pasta “publish” do seu projeto.

Por fim, clique em “Finish” para concluir o assistente. Ao fazer isso, uma primeira publicação será efetuada dentro da pasta indicada nas configurações. Para instalar a aplicação, basta executarmos o arquivo “setup“:

Uma vez instalada a aplicação, ela buscará atualizações na URL indicada no processo de deployment sempre que ela for iniciada e, quando uma nova versão estiver disponível, o usuário poderá escolher se quer instalar ou não a versão atualizada:

E com isso o nosso instalador / atualizador feito com o ClickOnce está pronto para ser instalado em um servidor de verdade (no IIS). Se você quiser ver como fazer a publicação com o ClickOnce no Azure, veja este excelente vídeo do André Secco onde ele mostra um passo-a-passo.

Desafios do ClickOnce

Como você pode ver, o ClickOnce é muito simples de ser configurado. Porém, ele não é somente mil maravilhas. Existem diversos desafios que temos que enfrentar ao utilizarmos o ClickOnce como ferramenta de deployment dos nossos aplicativos.

– Instalação somente para um usuário

O primeiro problema é que a instalação é feita somente para o usuário que está executando o instalador. Ou seja, não dá para instalar a aplicação para todos os usuários (opção bem conhecida em diversas ferramentas de instaladores). Outro problema é que, como o setup roda no contexto do usuário, não é possível executá-lo como administrador. Isso acaba limitando as tarefas que podem ser feitas durante a instalação. Você quer rodar um arquivo batch que precisa de permissão de administrador durante a instalação? Pode esquecer, com o ClickOnce não é possível.

– Local da instalação não customizável

Esse é o ponto que mais me deixa irritado na instalação com o ClickOnce. O usuário não pode escolher o local onde a aplicação será instalada. E o pior de tudo é que o local de aplicação é um lugar bem nas entranhas no sistema de arquivos (dentro de alguma subpasta de “C:\Users\NomeDoUsuario\AppData\Local\Apps\2.0“, local onde todas as aplicações ClickOnce são instaladas). Portanto, se a sua aplicação precisa obrigatoriamente estar rodando em uma pasta específica, você terá problemas com o ClickOnce.

– UI não customizável

Não é possível customizar a experiência de instalação do ClickOnce. O assistente de instalação é engessado e a única coisa que você consegue alterar é o idioma.

– Certificados necessários para não cair no Smart Screen

Se você tentar instalar e rodar uma aplicação distribuída com o ClickOnce no Windows 8 ou superior, você receberá uma mensagem do Smart Screen, que dirá que a aplicação que você está tentando instalar / rodar provavelmente não é confiável:

Isso acontece porque o Smart Screen só reconhece como “confiáveis” aplicações distribuídas com o ClickOnce que estejam assinadas por um certificado reconhecido. Ou seja, se você quiser remover esse anúncio irritante do Smart Screen no Windows 8 ou Windows 10, você terá que comprar um certificado para assinar a sua aplicação.

Opção 2: NAppUpdate

Para a nossa sorte, o ClickOnce não é a única ferramenta que podemos utilizar para implementarmos atualizações automáticas nas nossas aplicações. Existem outras ferramentas gratuitas (e open source) que implementam esse tipo de funcionalidade. A primeira ferramenta que eu quero mostrar além do ClickOnce é a NAppUpdate.

O NAppUpdate nada mais é que uma biblioteca que implementa a funcionalidade de atualização automática para aplicações .NET. Ela é uma biblioteca open source e você encontra todo o seu código fonte diretamente no GitHub.

Como o NAppUpdate está disponível no NuGet, para começarmos a utilizá-lo na nossa aplicação, basta adicionarmos uma referência:

Uma vez adicionada a referência, nós podemos utilizar as classes do NAppUpdate, que ficam dentro do namespace “NAppUpdate.Framework“. Porém, antes de codificarmos qualquer coisa com o NAppUpdate, vamos entender como é que ele funciona.

Primeiramente, o NAppUpdate não é um instalador, mas sim, somente um atualizador de aplicações. Isso quer dizer que a primeira versão da sua aplicação deverá ser distribuída através de um instalador convencional (como eu mostrei neste outro artigo). Uma vez instalada a aplicação no computador do cliente, nós podemos utilizar o poder do NAppUpdate para checarmos por atualizações.

A ideia do NAppUpdate é que nós teremos um arquivo de manifesto em algum lugar acessível (em um servidor web ou FTP, por exemplo). Esse arquivo de manifesto é um XML contendo tarefas que deverão ser executadas quando a aplicação for atualizada. Até o momento, existem dois tipos de tarefas: FileUpdateTask e RegistryTask, que servem para atualizar um arquivo ou uma entrada no registro, respectivamente.

Cada tarefa pode ter condições, que indicarão se elas serão ou não executadas, dependendo da versão que o usuário estiver rodando. Por exemplo, nós podemos configurar uma ação que substituirá o executável da nossa aplicação caso a versão instalada no computador do usuário seja menor que um certo número. No exemplo de manifesto abaixo, veja como podemos configurar o NAppUpdate de forma que ele atualize o executável da aplicação (AtualizadorAplicacao.exe) caso o arquivo no computador do usuário tenha uma versão menor do que “1.0.1.0“:

<?xml version="1.0" encoding="utf-8"?>
<Feed>
  <Tasks>
    <FileUpdateTask hotswap="false" updateTo="file://d:\tmp\update\AtualizadorAplicacao.exe" localPath="AtualizadorAplicacao.exe">
      <Description>Descricao da nova versao.</Description>
      <Conditions>
        <FileVersionCondition what="below" version="1.0.1.0" />
      </Conditions>
    </FileUpdateTask>
  </Tasks>
</Feed>

Vamos analisar com calma o conteúdo desse XML. Primeiramente, temos uma “FileUploadTask” com a propriedade “hotswap” definida como “false“. O “hotswap” indica se o arquivo pode ser substituído com a aplicação rodando ou não. Como nós estamos atualizando o próprio executável da aplicação, ele obviamente não poderá ser substituído com a aplicação em execução, então temos que definir “hotswap” como “false“. Caso você tente deixa-lo como “true“, o NAppUpdate não conseguirá fazer a atualização e retornará um erro parecido com este, dizendo que o arquivo está bloqueado:

Em seguida, temos o atributo “updateTo“, que definirá o caminho da versão mais atualizada do arquivo. No exemplo acima, estou utilizando um endereço que aponta para um arquivo em disco. Obviamente, em um deployment de verdade, o valor deverá ser um endereço acessível pela internet (ou intranet caso a aplicação seja interna). O NAppUpdate não verificará se o arquivo existe antes de tentar baixa-lo. Ou seja, se ele não encontrar o arquivo no caminho especificado, uma exceção será lançada:

O próximo atributo “localPath” corresponde ao caminho relativo do arquivo que será atualizado, tomando como base o diretório onde a aplicação está instalada. Se você quiser atualizar um arquivo que esteja em outra pasta, basta indicar o caminho completo nesse atributo.

Dentro da tarefa de atualização do arquivo, nós temos a condição que a atualização só deverá ser feita caso a versão atual no computador do usuário seja menor do que “1.0.1.0“. Aqui vale a pena mencionar que o NAppUpdate trabalha com o número de versão do arquivo, e não do assembly, portanto, tome cuidado com esse detalhe.

A implementação das outras opções de condições pode ser encontrada neste link. A condição “FileChecksumCondition” pode ser utilizada para atualizar um arquivo caso o seu check-sum corresponda a um valor específico (mais informações sobre check-sum MD5 e SHA neste meu outro artigo). Além disso, podemos utilizar também a “FileDateCondition” para atualizar um arquivo caso ele seja mais velho do que uma data específica ou a “FileSizeCondition“, que faz o mesmo considerando o tamanho do arquivo. Temos também a “FileExistsCondition“, que simplesmente atualiza o arquivo caso ele exista no computador do cliente e a “OSCondition“, para checar se o sistema operacional é 32 bits ou 64 bits. Por fim, com a “BooleanCondition” nós conseguimos agrupar várias condições em uma só.

Agora que já vimos um pouco da estrutura do arquivo de manifesto do NAppUpdate, vamos ver como é que fica o código para atualizarmos a nossa aplicação. Primeiramente, o NAppUpdate trabalha com o conceito de “singleton“. Isso quer dizer que somente uma instância dele será criada de cada vez. Ou melhor, no caso do NAppUpdate, essa instância já está criada e pode ser acessada através da propriedade “NAppUpdate.Framework.UpdateManager.Instance“.

Dentro dessa instância, a primeira coisa que temos que configurar é o caminho do arquivo de manifesto. Fazemos isso através da propriedade “UpdateSource“. Em seguida, nós chamamos o método “CheckForUpdates” e, caso alguma atualização esteja disponível (propriedade “UpdatesAvailable“), nós chamamos os métodos “PrepareUpdate” (para baixar a atualização) e “ApplyUpdate” (para instalar a atualização). Uma das sobrecargas do método “ApplyUpdate” recebe um valor booleano, indicando se a aplicação deve ser reiniciada após a atualização ou não:

            // C#
            var updateManager = NAppUpdate.Framework.UpdateManager.Instance;
            updateManager.UpdateSource = new NAppUpdate.Framework.Sources.SimpleWebSource(@"file://d:\tmp\nappupdate.xml");
            updateManager.CheckForUpdates();
            if (updateManager.UpdatesAvailable > 0)
            {
                updateManager.PrepareUpdates();
                updateManager.ApplyUpdates(true);
            }
        ' VB.NET
        Dim UpdateManager = NAppUpdate.Framework.UpdateManager.Instance
        UpdateManager.UpdateSource = New NAppUpdate.Framework.Sources.SimpleWebSource("file://d:\tmp\nappupdate.xml")
        UpdateManager.CheckForUpdates()
        If UpdateManager.UpdatesAvailable > 0 Then
            UpdateManager.PrepareUpdates()
            UpdateManager.ApplyUpdates(True)
        End If

Um detalhe importante com o NAppUpdate é que ele disparará uma exceção se o caminho para o arquivo de manifesto não estiver disponível:

Dito isso, é recomendado que você envolva todo o código relacionado ao NAppUpdate em um bloco try-catch, dessa forma nós evitamos crashes da aplicação. Afinal de contas, não vai cair nada bem se a nossa aplicação estiver crashando na hora de procurar por atualizações.

Enfim, se recompilarmos o projeto e tentarmos executá-lo, o NAppUpdate indicará que uma atualização está disponível (porque nós configuramos a versão do arquivo como “1.0.0.0” nas propriedades do projeto). Em seguida, ele baixará a nova versão do endereço indicado, fechará a aplicação para fazer a substituição do arquivo, porém, ele não conseguirá carregar a aplicação novamente caso estejamos executando através do Visual Studio:

Isso acontece porque, quando iniciamos o modo de debug do Visual Studio, ele não executa diretamente a aplicação, mas sim, uma outra cópia do nosso executável (com final “vshost.exe“). Para contornarmos esse problema, nós temos que executar a aplicação sem estar em modo debug (ou podemos executar a aplicação diretamente pelo Windows Explorer).

Para evitarmos problemas de loop infinito com o NAppUpdate e para detectarmos se a atualização foi realizada com sucesso na próxima execução da aplicação, nós temos que chamar o método “ReinstateIfRestarted” (nos casos em que a nossa aplicação tenha que ser reiniciada ao aplicar a atualização). Ao fazermos isso, nós receberemos um outro erro:

Esse erro acontece porque, uma vez aplicado o update, nós não podemos chamar o método “CheckForUpdates” novamente na próxima execução da aplicação. O código correto nesse caso inclui a verificação do estado do “UpdateManager“. Nós só seguiremos com a checagem das atualizações caso o código ainda não tenha sido executado. Veja como fica o código final para implementarmos a checagem e aplicação de atualizações automáticas no nosso aplicativo:

            // C#
            var updateManager = NAppUpdate.Framework.UpdateManager.Instance;
            updateManager.UpdateSource = new NAppUpdate.Framework.Sources.SimpleWebSource(@"file://d:\tmp\nappupdate.xml");
            updateManager.ReinstateIfRestarted();
            if (updateManager.State == NAppUpdate.Framework.UpdateManager.UpdateProcessState.NotChecked)
            {
                updateManager.CheckForUpdates();
                if (updateManager.UpdatesAvailable > 0)
                {
                    updateManager.PrepareUpdates();
                    updateManager.ApplyUpdates(true);
                }
            }
        ' VB.NET
        Dim UpdateManager = NAppUpdate.Framework.UpdateManager.Instance
        UpdateManager.UpdateSource = New NAppUpdate.Framework.Sources.SimpleWebSource("file://d:\tmp\nappupdate.xml")
        UpdateManager.ReinstateIfRestarted()
        If UpdateManager.State = NAppUpdate.Framework.UpdateManager.UpdateProcessState.NotChecked Then
            UpdateManager.CheckForUpdates()
            If UpdateManager.UpdatesAvailable > 0 Then
                UpdateManager.PrepareUpdates()
                UpdateManager.ApplyUpdates(True)
            End If
        End If

É claro que dessa forma nós não estamos dando a opção de o usuário instalar ou não a atualização (nós estamos fazendo de maneira “invisível“). Caso você queira dar essa opção para os seus usuários, você terá que implementar a interface por conta própria.

E com isso nós vimos como atualizar aplicações .NET automaticamente utilizando o NAppUpdate. Para mais informações sobre essa biblioteca, confira estes links:

The philosophy behind NAppUpdate

NAppUpdate – Application auto-update framework for .NET

Atenção! O NAppUpdate está ficando “sem dono”

Um detalhe que não posso deixar de mencionar aqui é que a pessoa que mais estava contribuindo com o NAppUpdate nos últimos tempos (o usuário “robinwassen” no GitHub) deixará de manter a biblioteca. Veja só a mensagem que ele deixou no GitHub da biblioteca algumas semanas atrás:

Isso pode ser preocupante caso alguém não assuma o desenvolvimento e manutenção da biblioteca nos próximos meses. Caso isso aconteça, as chances de a biblioteca acabar morrendo são grandes.

Opção 3: AutoUpdater.NET

Uma última opção de atualizador automático que eu quero mostrar para vocês nesse artigo é o AutoUpdater.NET. Ele também é uma biblioteca open source que implementa atualizações automáticas para aplicações .NET. A ideia é muito parecida com o NAppUpdate (aliás, a ideia do NAppUpdate veio dessa biblioteca). Através de um arquivo de manifesto, a biblioteca identificará se existe uma atualização disponível e, caso positivo, ela fará o download e instalação dessa atualização.

O arquivo de manifesto do AutoUpdater é muito mais simples do que o arquivo de manifesto do NAppUpdate. No caso do AutoUpdater, o XML contém somente um elemento chamado “version” (que indicará o número da versão que está disponível para download) e um outro elemento chamado “url“, que será o local de onde o AutoUpdater baixará a atualização para ser instalada:

<?xml version="1.0" encoding="UTF-8"?>
<item>
    <version>1.0.1.0</version>
    <url>file://d:\tmp\update\AtualizadorAplicacao.zip</url>
</item>

No exemplo de manifesto acima, estamos dizendo para o AutoUpdater que a versão “1.0.1.0” está disponível para ser baixada no caminho indicado. Com essa informação, o AutoUpdater verificará se a versão da aplicação é menor do que esse número e, caso positivo, ele entenderá que uma atualização está disponível. Um ponto importante é que, diferente do NAppUpdate (que trabalha com as versões dos arquivos), o AutoUpdater trabalha com a versão do assembly “entry point” da aplicação (ou seja, a versão do assembly do executável).

Para o elemento “url“, nós temos duas opções. A primeira delas é indicarmos o caminho para um executável. Com essa opção, nós teríamos que gerar um instalador (utilizando alguma outra ferramenta de instalador) contendo a versão mais nova da aplicação. Esse executável seria baixado e executado quando o usuário clicasse na opção para atualizar a aplicação.

Uma segunda opção para esse elemento é informarmos o caminho de um arquivo zip. Nesse caso, o AutoUpdater baixará o arquivo zip e descompactará na pasta da aplicação. Ou seja, basta ziparmos o executável e dlls da versão mais nova e o AutoUpdater se encarrega de descompactar no diretório da aplicação.

Seguindo o mesmo padrão do NAppUpdate, a biblioteca AutoUpdater também está disponível através do NuGet (só tome cuidado para adicionar a referência para o pacote oficial!):

Uma vez adicionada a referência, nós podemos acessar a classe do AutoUpdater, que fica no namespace “AutoUpdaterDotNET“. Com apenas uma linha de código nós conseguimos fazer a checagem de atualizações na nossa aplicação:

// C#
AutoUpdaterDotNET.AutoUpdater.Start(@"file://d:\tmp\autoupdater.xml");
' VB.NET
AutoUpdaterDotNET.AutoUpdater.Start("file://d:\tmp\autoupdater.xml")

O esquema do AutoUpdater é um pouco diferente do NAppUpdate. No caso do AutoUpdater, ele mesmo implementa uma interface padrão para facilitar a nossa vida. Uma vez que o AutoUpdater encontra uma nova versão para ser instalada, ele exibirá uma janela onde podemos escolher o que queremos fazer:

Note que a janela será exibida no idioma da região que estiver selecionada no sistema operacional (no meu caso em alemão, uma vez que a região do meu computador está definida como Alemanha). Se quiser alterar para um idioma específico, basta utilizar a propriedade CurrentCulture da classe AutoUpdater. No próprio GitHub da biblioteca conseguimos encontrar diversos exemplos de configurações específicas que podemos utilizar nas nossas aplicações. Por exemplo, nós podemos desabilitar o botão de “Skip“, o botão de “Remind later“, etc. E, caso você não tenha gostado da interface disponibilizada pelo AutoUpdater, você pode criar a sua própria interface para gerenciar a checagem de atualizações também (utilizando o evento “CheckForUpdateEvent“).

E com isso nós vimos como implementar atualizar as nossas aplicações .NET automaticamente utilizando a biblioteca AutoUpdater. Muito mais simples que o NAppUpdate, porém, menos flexível.

Squirrel: outra opção que eu não investiguei

Uma outra opção que eu acabei de encontrar enquanto estava escrevendo o artigo é o Squirrel, que também é uma biblioteca open source. O lema dessa biblioteca é “It’s like ClickOnce but Works“, então vale a pena dar uma olhada. Se você já tiver trabalhado com o Squirrel, deixe as suas impressões nos comentários.

Baixe o projeto de exemplo

Para baixar o projeto de exemplo desse artigo, assine a minha newsletter. Ao fazer isso, além de ter acesso ao projeto, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário no final do artigo.

Concluindo

No artigo de hoje você conferiu tudo sobre aplicações que se atualizam sozinhas no .NET. Para conseguir essa façanha, temos que utilizar ferramentas de apoio.

A primeira ferramenta apresentada neste artigo foi o ClickOnce, que é uma ferramenta da própria Microsoft que implementa a funcionalidade de instalação e atualização automática de aplicações desktop. Apesar de ser bastante útil e fácil de utilizar, o ClickOnce vem com alguns problemas de brinde.

Em seguida, você conferiu como podemos utilizar a biblioteca NAppUpdate para fazer a atualização automática das nossas aplicações .NET. Ela é uma biblioteca um pouco complexa, porém, extremamente flexível.

Por fim, nós analisamos a biblioteca AutoUpdater.NET, que é bem mais simples do que a NAppUpdate, entretanto, com poucas flexibilidades no que diz respeito ao arquivo de manifesto de atualizações.

Dessas três opções, qual é a minha preferida? Confesso a você que eu só utilizei o ClickOnce em produção há muito tempo atrás. Hoje eu dia eu particularmente não utilizaria o ClickOnce se tivesse que fazer uma aplicação auto-atualizável. Se você precisa de bastante flexibilidade na hora de atualizar a sua aplicação, eu recomendo o NAppUpdate. Agora, se um simples arquivo zip descompactado já resolve a atualização da sua aplicação, acredito que o AutoUpdater seja a melhor opção.

E você? Já precisou atualizar aplicações desktop automaticamente? Qual tecnologia você utilizou? Encontrou algum desafio na implementação? Fico aguardando um relato das suas experiências logo abaixo na caixa de comentários!

Até a próxima!

André Lima

Photo by Pixabay used under Creative Commons
https://pixabay.com/en/update-upgrade-renew-improve-1672349/

Newsletter do André Lima

* indicates required



Powered by MailChimp

17 thoughts on “Como atualizar aplicações .NET automaticamente?

  • Lucas Almeida disse:

    Bom dia André, excelente artigo. Eu particularmente utilizei o ClickOnce em um projeto interno. Porém o mais chato dele como você próprio mencionou é o fato de não se poder escolher um destino na para nossa aplicação e também ter que comprar um certificado para assinar aplicação. Como é um aplicativo interno, optamos por não comprar um certificado, porém toda vez que vai instalar a primeira vez o aplicativo o usuário ‘grita’ falando que está instalando um programa não confiável…daí tem que explicar e bla bla bla…Vou testar as outras opção, gostei do NAppUpdate, porém o fato de que ela está ficando sem dono me deixou também preocupado. Abraços

    • andrealveslima disse:

      Olá Lucas, muito obrigado pelo comentário!

      Realmente o ClickOnce tem as suas chatices, como você falou.. O NAppUpdate me pareceu ser bem robusto.. Não sei se precisamos nos preocupar tanto assim com o principal colaborador estar abandonando o barco.. Acredito que alguém vá assumir o desenvolvimento algum dia desses.. Sem falar que a biblioteca já está um tanto quanto madura.. Vale a pena pelo menos testar para ver se encaixa bem no seu cenário de deployment..

      Enfim, depois volta aqui pra contar pra gente quais foram os resultados..

      Abraço!
      André Lima

  • deuzivaldo disse:

    Ótimo professor, muito bom, adorei. Ah professor, sobre aquele meu projeto, eu estou criando ele do zero de novo porque não funcionou mais. Não sei o que aconteceu. Obrigado por você ter me ajudado. Tenha um bom dia

  • Tadeu Botelho disse:

    Olá André!

    Obrigado por mais essa contribuição. Pois me ajudou muito ao dar uma olhada em suas explicações e observações em relação aos atualizadores.

    Fiz alguns testes com eles e realmente os achei um pouco limitados em relação aos recursos disponíveis. Mas o princípio é o mesmo do atualizador que estou aperfeiçoando, para atualização de vários sistemas que funcionam em conjunto, dentro da mesma plataforma compartilhada entre ambos. Ou seja: Tenho o sistema 01, sistema 02, sistema 03… (Desenvolvidos com linguagens diferentes e conversando entre si de maneira integrada), todos estão sendo atualizados por um software que já existe há 10 anos. Porém, agora seus recursos de atualização estão sendo remontados para operar online. Os desafios estão em questões de otimização. E na construção, estou utilizando C# com recursos da .Net e esta ficando muito bom.

    Tenho acompanhado suas publicações há alguns meses. Quero parabenizá-lo e incentivá-lo a manter seus textos em atividade. Pois são bem esclarecedores pelo fato de exibirem vários assuntos bem bacanas (Como os atualizadores de hoje).

    Grande abraço

    • andrealveslima disse:

      Olá Tadeu, muito obrigado pelo elogio! Eu que agradeço por você ter acompanhado as publicações.. :)

      Desconsiderando o ClickOnce, o que exatamente você achou limitado nas outras bibliotecas? Aqui onde eu trabalho a gente também tem um atualizador próprio para um sistema específico.. Só que ele funciona basicamente seguindo a mesma ideia dessas bibliotecas.. Se soubéssemos da existência delas anteriormente, provavelmente não teríamos desenvolvido um sistema próprio..

      Um forte abraço!
      André Lima

  • Giancarlo Carraro disse:

    Excelente artigo. Nunca gostei do ClickOnce pelas limitações dele, mas fiquei sem tempo de procurar outras soluções então acabei utilizando “quebra-galhos”. Vai me ajudar muito as suas observações.
    Obrigado por dedicar o seu tempo a nos ajudar.

    • andrealveslima disse:

      Olá Giancarlo, muito obrigado pelo comentário! Espero que você goste das outras opções além do ClickOnce.. :)

      Qualquer coisa estamos aí..

      Abraço!
      André Lima

  • ANDRE LUIZ G DIOGO disse:

    Boa Tarde… excelente tópico, novamente meus parabéns…

    Eu trabalho atualizando varias tipos de executáveis a partir de um http://FTP.. a ideia é um aplicativo que conecta no FTP e verifica as versões em um TXT que segue um layout separados por pipe (Nome | Versão | Local Destino ) mais ou menos assim.. pois txt qualquer máquina consegue ler.. o atualizador ao ver que existe um novo exe na base de dados em txt, faz o download do executável via FTP e substitui o anterior.. foi esta maneira que encontrei para poder trabalhar com vários programas de fornecedores distintos e com recurso do http://FTP... mas show de bola. .espero um dia poder melhorar meu programa de atualização para ficar mais robusto… uma falha que ainda não corrigi é de não verificar o md5 apos download, pode ser que as vezes possa vim corrompido :(

    abraço André e obrigado pelos tópicos…

    • andrealveslima disse:

      Olá André, muito obrigado pelo comentário!

      Não tem problema nenhum construir uma sistemática própria de atualização.. Aqui onde eu trabalho nós construimos uma customizada também, baseada em web services.. Só é importante conhecer as ferramentas que já trazem essa funcionalidade pronta, dessa forma sempre que precisarmos desse tipo de atualização automática em algum projeto, podemos analisar se essas soluções prontas já não atendem à demanda..

      Quanto ao esquema do MD5, eu escrevi um artigo sobre comparação de hashes de arquivos.. Não sei se você chegou a dar uma olhada:

      Calculando o hash de arquivos para verificação de integridade com C# e VB.NET

      Talvez te ajude na hora de implementar essa checagem no seu sistema de atualização..

      Abraço!
      André Lima

  • Sidney disse:

    Como faria para atualizar vários arquivos da aplicação utilizando o NappUpdate?
    Pois dependendo da versão ele poderá conter outras dependências/dll, teria que criar um xml para cada arquivo?

    • andrealveslima disse:

      Olá Sidney!

      Eu particularmente não testei, mas a ideia é que você tenha várias tags “FileUpdateTask” no mesmo XML de definição.. Cada tag dessa corresponderia a um arquivo que deverá ser atualizado.. Entendeu a ideia?

      Abraço!
      André Lima

  • WEDER FRANÇA disse:

    Olá André, bom dia!
    Parabens pelo conteudo, muito bem explicado.
    Sou iniciante em c# e criei uma aplicação windows form.
    para usar o clickOnce terei que criar uma pagina na internet
    para atualização do aplicado? esta seria a unica forma de uma
    atualização automática?
    abraços…

    • andrealveslima disse:

      Olá Weder, muito obrigado pelo comentário!

      Se você quiser ter uma atualização automática, independente da opção que você escolher, você precisará de qualquer forma disponibilizar as versões em um local (servidor) acessível pela internet.. Com o ClickOnce você precisa sim de um servidor web (IIS) rodando por trás dos panos.. Se o Azure for uma opção para você, recomendo este vídeo do André Secco, que eu mencionei no meio do artigo:

      Implantação de aplicativos Auto-Atualizáveis com o ClickOnce

      Agora, se esse tipo de estrutura for muito complexa para você manter, recomendo que você dê uma olhada nas outras opções de ferramentas / bibliotecas que eu apresentei no artigo..

      Abraço!
      André Lima

      • WEDER FRANÇA disse:

        Obrigado Andre!

        Então, como disse ainda estou iniciando no mundo de TI.
        Criei um sistema de “Ordem de Servico” e recentemente acrescentei
        nele a emissão de “Nota fiscal Eletronica.
        Agora o cliente gera a OS e caso queira a NFe também.
        Hoje tem apenas 3 pessoas usando, e as atualizações sempre envio por email, mas vejo que esta prática não é a melhor.
        o certo seria assim que o cliente acessar o sistema já buscar atualizações.
        Vou ter que aprofundar na criação de uma pagina na internet para disponibilizar estes arquivos então.
        Vai ser outra batalha, nunca mexi com programação web. rrsrsrs

        • andrealveslima disse:

          Olá Weder!

          Entendi o seu cenário.. Não se preocupe, o conhecimento que você terá que ter para disponibilizar as novas versões na web não será muito grande.. Se você ficar com alguma dúvida no processo, é só entrar em contato..

          Abraço!
          André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *