Install personalizado 2.0
Melhorando o instalador

Muito tempo se passou desde a primeira versão do install personalizado. A internet virou um sucesso, já estamos na versão 8 do Delphi, as políticas do governo... digo, algumas coisas mudaram. Mas a necessidade de um bom instalador não.

Portanto, chegou a hora de um update. Usando as mais modernas (e as nem tão modernas) técnicas de programação, vamos criar uma nova versão do install personalizado da TILT. Agora ele vêm com código fonte completo, afinado para as novas necessiadades de distribuição que a internet impõe aos softwares em geral.

Trabalhos Iniciais

Quais os objetivos do novo instalador? Em primeiro lugar, reduzir o tamanho dos arquivos que serão distribuídos e em segundo lugar reduzir o número de volumes utilizados para transferir o programa (ou seja, a quantidade de arquivos que precisarão ser enviados juntos).

Este segundo objetivo é um claro ajuste aos novos problemas que a internet traz na distribuição de conteúdo: é melhor fazer o download de apenas um arquivo (mesmo que seja um pouco maior do que o estritamente necessário) do que obrigar o usuário a "caçar" diversos pequenos componentes de uma aplicação.

Portanto, o sucesso será obtido construindo um programa instalador que inclua todos os arquivos necessários para sua execução (contando os arquivos do programa que será instalado) e que possa ser distribuído sozinho, sem a necessidade de qualquer outro utilitário ou biblioteca externa.

Mas como fazer?

O Delphi é um grande amigo nessas horas de dificuldade. Na verdade, o Windows também é um grande amigo nessas horas de dificultade, não importando a má fama que muitas pessoas insistem em lhe atribuir.

Todo programa Windows contém uma área dentro do seu executável que guarda uma série de arquivos de recurso (resource files) que contém desde os ícones que o programa usa até sons, informação de menus, imagens, etc.

De maneira geral, o Delphi gerencia esses arquivos automaticamente. É por causa desses arquivos que quando uma imagem é colocada em um TImage e o projeto é compilado, o arquivo original pode até ser deletado que a imagem dentro do programa não será perdida: ela estará dentro de um recurso nessa área específica do executável.

Com esse conhecimento, a idéia mais simples, fácil e rápida de se criar o instalador seria a de inserir um resource file dentro do projeto Delphi que contenha todos os arquivos que devem ser transportados. Moleza, certo?

Bem, nem tanto. O problema é que esses arquivos não executam qualquer tipo de compressão. E essa é uma das razões pelas quais um formulário com imagens gera um programa tão grande: elas foram salvas em arquivos não comprimidos.

A solução para esse dilema fica clara examinando o artigo Trocando de Peles aqui mesmo da TILT: compactar todos os arquivos da aplicação e então colocar esse pacote dentro do resource file.

Agora sim, essa parece a solução ideal: a compactação gera um pacote reduzido que diminuirá o espaço total gasto pelo instalador, e colocando-o dentro do executável é possível criar um único volume que pode ser distribuído sozinho - e melhor de tudo, que pode ser customizado como qualquer programa ou jogo criado no Delphi.

Criando o arquivo de Recursos

Os resource files (extensão .res) são criados a partir de arquivos de script (extensão .rc) com o auxílio de compiladores especiais. Como a Borland é camarada, o Delphi já vêm com um compilador chamado criativamente de Borland Resource Compiler. Se a instalação foi feita corretamente, o compilador pode ser executado simplesmente digitando-se brc32 no prompt de comando.

Para simplificar as coisas, criamos um arquivo de lotes que invoca o compilador para um pacote zip chamado de "arquivos.zip" que deve conter todos os arquivos necessários para a execução do programa que será instalado. Portanto, para modificar o instalador (além é claro de colocar suas próprias imagens) tudo o que precisará ser feito é atualizar esse pacote, rodar o bat e recompilar o projeto.

Mas apenas gerar o resource file não é o suficiente: é preciso incluí-lo na aplicação. Isso é feito através da diretiva {$RESOURCE arquivos.res} (ou {$R arquivos.res}), que deve ser incluída logo após a declaração dos recursos do próprio formulário (a sempre presente {$R *.dfm}).

Inserir é simples o suficiente, mas como extrair os recursos? Para isso é preciso criar um objeto da classe TResourceStream que indique qual o nome, tipo e local do recurso que se deseja pegar. Colocando essa parte do código em um procedimento à parte, ele fica:

procedure TForm1.lerZipDoResource;
var
  str: TResourceStream;
begin
  //arquivo zip
  str:= TResourceStream.Create(hInstance, 'arquivos',
                                                RT_RCDATA);
  str.SaveToFile(appdir + '~arquivos.zip');
  str.free;
end;

A variável hInstance indica que o recurso deve ser pêgo do próprio programa, arquivos é o identificador do recurso (que é escolhido no script que constrói o resource file) e RT_RCDATA é o tipo do recurso desejado (tipo binário).

Com o arquivo zip retirado do executável e salvo disco rígido, agora ficou até sem graça o resto do programa. Ele usa os mesmos conceitos do artigo sobre skins: abrir o arquivo zip, ler o conteúdo e fechá-lo. O trecho mais importante desse código é o seguinte:

  //pegar o nome de todos os arquivos do zip
  arqs.Text:= zipdllListarArqs;
  //extrair arquivos
  for i:= 0 to arqs.Count -1 do begin
    //se for um diretório (e não arquivo) pular
    if arqs[i][length(arqs[i])] = '\' then begin
      progbar.Position:= progbar.position + 1;
      continue;
    end;
    //arquivo final
    arq:= destDir + arqs[i];
    //força a criação da árvore até o arquivo
    ForceDirectories(extractFilePath(arq));
    //ler para o stream, salvar e limpar stream
    zipLerParaStream(arqs[i], str);
    str.SaveToFile(arq);
    str.clear;
  end;

A primeira tarefa feita é pegar o nome de todos os arquivos dentro do pacote zip e colocá-los em um TStringList (arqs). Após isto, cada arquivo do pacote será lido para um TMemoryStream e logo em seguida salvo para o diretório desejado (incluindo subpastas). Pronto, está feito o instalador.

Ou quase. Existe um pequenino problema que talvez tenha passado desapercebido. A manipulação de arquivos zip requer o uso da biblioteca dinâmica zipdll, que precisa estar no mesmo diretório do instalador ou no diretório system do windows.

Mas a proposta inicial havia sido a de criar um instalador completo, que pudesse ser distribuído sem qualquer vínculo externo, portanto o que fazer?

Simples. Incluir também a dll dentro do executável, do mesmo modo que o pacote zip foi incluso. A única questão é que será preciso uma pequena modificação do arquivo zipdllimport.pas, que precisa ter o carregamento automático da biblioteca desligada.

Por que? Porque as dlls podem ser ligadas ao executável de duas maneiras: estaticamente ou dinamicamente. Quando elas são ligadas de maneira estática, assim que o programa é iniciado elas são carregadas para a memória e as funções ficam disponíveis ao programador. No entanto, isso requer que o arquivo da biblioteca esteja disponível logo após o programa ter sido iniciado, o que não acontece nesse caso.

Nesse projeto é preciso retirar a dll de dentro do executável antes que seja possível carregá-la. Portanto é preciso fazer um carregamento dinâmico dela: o que significa chamar o procedimento zipInitDll depois que ela for extraída para o sistema.

Agora sim o programa está completo. Ele pode ser distribuído sozinho, e é completamente customizável às necessidades de cada projeto. Por exemplo, ele poderia checar as configurações do usuário e fazer o download de componentes extras de um site, poderia exibir uma tela de registro ou imagens da aplicação sendo instalada.

O código fonte desse artigo está disponível para download, usando é claro o próprio instalador para copiar os arquivos. Experimente, mude ajuste-o à sua própria maneira, e boa programação.


Download...
Clique no link para fazer o download dos arquivos. Se sua assinatura do club TILT está para vencer, clique aqui e saiba como renová-la.

Fontes e DLLs para criar o seu install personalizado
 
online