Criando instaladores para Windows com o Inno Setup

Criando instaladores para Windows com o Inno Setup
O Inno Setup é um gerador de programas de instalação para Windows, gratuito e de código aberto. É um dos instaladores mais bem feitos e usados, concorre diretamente com muitos softwares comerciais do tipo.

Voltado a desenvolvedores diversos, ele facilita a criação de um programa de instalação para suas aplicações, com um visual moderno e clássico de instalador, se mantendo prático e cheio de recursos. Ter um instalador próprio mal feito ou feito na correria pode ser ruim para seus programas, é bom preparar uma instalação bem feita – afinal, o primeiro contato dos usuários com seu programa geralmente se dá durante a instalação 🙂

Entre várias outras coisas, o Inno Setup permite criar chaves no registro e em arquivos INI, além do básico de um instalador: copiar arquivos para alguma pasta e a criação de atalhos. Ele tem várias propriedades que podem ser configuradas, como limitar a instalação a somente administradores, registrar DLL/OCX, instalar fontes, e muito mais. Ainda cria um desinstalador, que pode remover completamente seu programa. Uma grande possibilidade é que ele tem suporte a uma espécie de “programação” interna, onde você pode personalizar o instalador usando algumas funções como se estivesse num ambiente de programação. É possível também chamar funções de DLLs, ou seja: as possibilidades são imensas.

Ele pode ser baixado em:

http://www.jrsoftware.org/

A geração dos instaladores com o Inno Setup se dá por meio de um script. O compilador dele lê o script e gera um executável, unindo seus arquivos, as configurações e o módulo do instalador (um executável pronto, que realizará a instalação baseando-se nas configurações definidas). O resultado é um único arquivo .exe, que pode ser facilmente distribuído. O instalador dos seus programas terá esta aparência:

m4609a6ff
A criação do script, que é basicamente um arquivo de texto puro (com a extensão .iss), pode ser feita digitando-se os comandos manualmente ou então usando o assistente de criação do Inno – que gera um projeto básico. A forma mais fácil de criar um novo instalador é usar o assistente, e depois modificar o arquivo do projeto manualmente. E claro, modificar várias vezes, compilar e testar, até ficar pronto 🙂

O assistente dele faz o básico, vou me concentrar em mostrar alguns pontos importantes para um bom instalador, como a criação de chaves no registro, e orientação sobre como “programar” no Inno Setup, dando exemplo de uso de uma DLL externa.

O assistente do Inno exibe algumas telas, basta você ir preenchendo com as informações do seu programa e avançando:

m142a134b

1ad2eb39
Ao final, ele tem um script básico, que você poderá modificar sem grandes dificuldades. Antes de começar, é bom ter organizado e separado os arquivos do seu programa. Deixe tudo o que deverá existir no sistema do usuário em uma pasta, com subpastas, se necessário – toda a estrutura será copiada. Separe também o texto da licença da aplicação, de preferência num arquivo TXT.

Iniciando o compilador do Inno Setup, escolha a opção “Create a new script using the Script Wizard”. Vá preenchendo as informações conforme solicitadas, e ao concluir, terá o script padrão gerado. Considerando que ele é um gerador de programas de instalação para um software que você tenha criado, não haverá dificuldade em passar pelo assistente. Para compilar seu projeto, tecle CTRL+F9, e para compilar e testar, F9 apenas (como no Delphi). Você pode usar os menus ou botões da barra de ferramentas também, claro. O ambiente do Inno funciona como um debugger, mostrando quando algo estiver errado (inclusive indicando a linha), além de exibir um log da instalação em andamento (enquanto você testar o instalador a partir da interface dele). O arquivo para ser distribuído será o setup.exe, que por padrão fica na pasta “Output”, onde estiver salvo o script.

A estrutura básica do script do Inno Setup é esta:

[Setup] ; NOTE: The value of AppId uniquely identifies this application.
; Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{4BD6DFD3-105A-4921-B253-3F15E6022B5C}
AppName=My Program
AppVerName=My Program 1.5
AppPublisher=My Company, Inc.
AppPublisherURL=http://www.example.com/
AppSupportURL=http://www.example.com/
AppUpdatesURL=http://www.example.com/
DefaultDirName={pf}My Program
DefaultGroupName=My Program
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes

[Languages] Name: “brazilianportuguese”; MessagesFile: “compiler:LanguagesBrazilianPortuguese.isl”

[Tasks] Name: “desktopicon”; Description: “{cm:CreateDesktopIcon}”; GroupDescription: “{cm:AdditionalIcons}”; Flags: unchecked

[Files] Source: “C:Program Files (x86)Inno Setup 5ExamplesMyProg.exe”; DestDir: “{app}”; Flags: ignoreversion
; NOTE: Don’t use “Flags: ignoreversion” on any shared system files

[Icons] Name: “{group}My Program”; Filename: “{app}MyProg.exe”
Name: “{commondesktop}My Program”; Filename: “{app}MyProg.exe”; Tasks: desktopicon

[Run] Filename: “{app}MyProg.exe”; Description: “{cm:LaunchProgram,My Program}”; Flags: nowait postinstall skipifsilent

Veja que o arquivo tem o estilo dos arquivos INI, sendo bem fácil de editar. Algumas seções permitem vários parâmetros, neste caso eles devem ser separados por ponto-e-vírgula, além de terem seu conteúdo declarado entre aspas, se tiver espaços.

A seção [Setup] define informações básicas do programa de instalação, como o nome da aplicação, URL do produtor, pasta padrão para instalação, etc. O Inno Setup usa algumas constantes de pastas próprias; você pode ver uma relação completa na ajuda dele. Por exemplo, {pf} retorna o caminho completo da pasta “Arquivos de programas” no sistema do usuário – independente do idioma do Windows ou partição em que ela esteja. Na seção [Setup], várias coisas podem ser ativadas ou desativadas, como a compressão, a exibição de uma licença de uso, a possibilidade de proteger a instalação com uma senha, entre muitas outras. As entradas nesta seção são simples, sendo basicamente no estilo Diretiva=Opção.

A seção [Languages], como o nome sugere, permite definir os idiomas da instalação. No assistente você pode escolher vários idiomas, ou modificar as entradas aqui, adicionando novas linhas para os idiomas desejados. Por exemplo, para manter o instalador em inglês e português, você colocaria:

[Languages]

Name: “brazilianportuguese”; MessagesFile: “compiler:LanguagesBrazilianPortuguese.isl”

Name: “english”; MessagesFile: “compiler:Default.isl”

O “Default.isl” é o arquvio de texto com as mensagens para inglês, ele está na pasta do Inno Setup (por isso pode-se usar “compiler:”, que retorna a pasta do compilador do Inno). O Inno Setup gera instaladores multi-linguagem, e caso tenha mais de um idioma definido, aparecerá uma caixa de diálogo para seleção da linguagem no começo da instalação.

Das outras seções, a [Files] é a mais importante. Ela define as pastas e arquivos que serão instalados no sistema. A [Icons] permite a criação de atalhos, a [Run] a execução de comandos logo após a conclusão da instalação, e a [Tasks] permite criar “tarefas”, itens de checkbox que aparecerão antes de iniciar a instalação, podendo ser marcados ou desmarcados pelo usuário. As entradas nas outras seções referenciando uma tarefa previamente definida na seção [Tasks] só serão executadas se o usuário deixar marcada a opção correspondente, durante a instalação.

O uso do Inno não é difícil, mas você precisa dedicar um tempinho até entender como as entradas do script dele se relacionam. Na pasta “Examples”, dentro da pasta do Inno, existem exemplos básicos sem muitas entradas – permitindo que você estude um assunto por vez. Nesse artigo vou destacar alguns meios de usar o Inno para gerar instaladores mais profissionais e responsáveis, sem ficar usando muito as opções “padrões” apenas.

Particularmente fiz algumas modificações no Inno Setup, e lancei um fork dele com o nome Mep Installer. Traduzi o programa inteiro e o conteúdo da ajuda (pelo menos dos recursos que mantive). O material serve como um ótimo tutorial e referência em português de boa parte dos recursos do Inno Setup, e pode ser lido sem precisar instalar o programa, em:

http://www.mephost.com/software/help/mpist14/ajuda.htm

Basta desconsiderar o que não se aplicar ao Inno 🙂

Visão geral de um instalador, e noções básicas

O instalador é o programa que vai instalar os arquivos e configurações do seu programa no sistema do usuário. É importante que ele seja bem feito, e responsável – que limpe tudo o que fizer, numa desinstalação. Algumas observações que você deve ter em mente:

  • É recomendável que o programa seja instalado apenas por um administrador. Usuários limitados não podem gravar coisas em chaves globais do registro, nem em pastas do sistema (como a Arquivos de programas). Apesar de ser possível o usuário gravar coisas nas suas pastas pessoais (podendo até instalar o programa nela, se as características da instalação permitir), com a vinda do Windows Vista e o XP, popular com o NTFS por padrão, é bom restringir a instalação aos administradores. No Windows XP com o HD formatado em FAT32, um usuário limitado até pode instalar coisas na Arquivos de programas, mesmo que não possa gravar dados em algumas chaves do registro. Já com o sistema de arquivos NTFS, padrão no Vista também, não tem como ele gravar dados na Arquivos de programas. Nas versões recentes do Inno Setup, por padrão, a instalação só pode ser feita por um administrador. Se quiser permitir que usuários limitados executem seu instalador, então adicione na seção [Setup] esta linha: PrivilegesRequired=none.
  • Na desinstalação, limpe tudo o que o seu programa colocar, mas tome o cuidado de não apagar arquivos do usuário. O Inno Setup remove uma boa parte do que ele faz na instalação automaticamente. Mas em algumas situações, alguns arquivos podem permanecer no HD. Tome o cuidado de remover estes arquivos (comentarei como logo mais).
  • Em coisas exclusivas do seu programa (pastas, chaves do registro e atalhos), use um nome que provavelmente só o seu programa use, para evitar conflitos com outros programas que possam existir no sistema do usuário.

Entendendo melhor o arquivo de projeto do Inno Setup

O arquivo de projeto é formado por seções, grupos de opções e configurações. Os nomes das seções são identificados entre colchetes, e aparecem em negrito na tela do compilador. Os itens referentes a uma determinada seção devem estar “dentro” dela. Algumas seções possuem itens como diretivas, idênticas aos arquivos INI. Por exemplo:

[Setup]

AppName=Meu Programa

AppPublisher=Meu nome

Outras seções podem possuir mais parâmetros, geralmente separados por um ponto-e-vírgula. Veja:

[Files]

Source: “MeuPrograma.exe”; DestDir: “{app}”

Não é recomendável especificar duas vezes uma mesma seção, coloque as diretivas ou parâmetros de uma mesma seção embaixo da mesma identificação dela.

Você pode colocar comentários dentro do script. Comentários são textos que não são compilados, eles apenas indicam alguma coisa, em especial para quem irá ler ou trabalhar com o script (“script” é o “texto” do arquivo de projeto). Basta iniciar uma linha com o ponto-e-vírgula:

; Isto é um comentário… Blá, Blá, Blá……

Se você possui um arquivo de projeto com informações que deverão se repetir em várias instalações, pode utilizar a diretiva #include. O conteúdo do arquivo indicado será inserido no local especificado, e após ele as informações que estiverem serão continuadas, como se fossem um arquivo só. A sintaxe é:

#include “meuarquivo.iss”

A extensão não precisa ser necessariamente .iss, pode ser outra se você quiser, como .txt, por exemplo.

O arquivo informado deverá estar na mesma pasta do arquivo de projeto, ou então você pode informar o caminho completo (por exemplo, “C:Minha pastaMeu arquivo.iss”). Se o arquivo estiver na mesma pasta do compilador, você pode utilizar assim: #include compiler:teste.iss. Aliás, “compiler:” será substituído pelo caminho da pasta do compilador, em diversas seções.

Parâmetros nas seções

Todas as seções do arquivo de projeto, com exceção de [Setup], [Messages], [CustomMessages], e [LangOptions], contém linhas separadas em parâmetros. Veja o seguinte exemplo, da seção [Files]:

[Files]

Source: “MEUPROGRAMA.EXE”; DestDir: “{app}”

Source: “AJUDA.HLP”; DestDir: “{app}”

Source: “LEIAME.TXT”; DestDir: “{app}”; Flags: isreadme

Cada parâmetro consiste em um nome, seguido por um identificador, e então um valor. Exceto em alguns poucos casos, os parâmetros são opcionais. Eles assumirão um valor padrão se não forem especificados. Múltiplos parâmetros em uma linha podem ser separados por ponto-e-vírgula, e podem estar em qualquer ordem.

Geralmente se utilizam aspas duplas (“) para definir o valor de um parâmetro definido pelo usuário, como por exemplo o nome de um arquivo. Usar aspas quase sempre não é obrigatório, mas é necessário quando o valor tiver espaços.

Se precisar utilizar aspas duplas em alguma definição, coloque duas aspas duplas consecutivas, para evitar conflito com as aspas delimitadoras do parâmetro. A linha a seguir:

“Este exemplo “”contém aspas”” embutidas”

Ficaria assim, após a compilação:

Este exemplo “contém aspas” embutidas

Se você quiser que o valor de um parâmetro seja uma única aspa dupla, utilize então quatro caracteres de aspas duplas: “”””. Os caracteres das extremidades cercam o valor como sendo um valor definido pelo usuário, e os dois do meio são para gerar um único caractere de aspa.

Instalação de arquivos: dicas úteis

O assistente de criação de script do Inno cria uma entrada para cada arquivo que você adicionar, na seção [Files]. Por exemplo:

[Files]

Source: “C:programaPrograma.exe”; DestDir: “{app}”; Flags: ignoreversion

Source: “C:programaLeiame.txt”; DestDir: “{app}”; Flags: ignoreversion

Source: “C:programaFunções.dll”; DestDir: “{app}”; Flags: ignoreversion

Conforme você for tendo muitos arquivos, ou pastas e subpastas, essa idéia pode ficar confusa. A minha recomendação é criar uma pasta e deixar nela todos os arquivos do seu programa, incluindo subpastas, exatamente como você quer que eles fiquem na pasta do seu programa no sistema dos usuários. Assim, a seção [Files] teria uma entrada só:

[Files]

Source: “C:programa*”; DestDir: “{app}”; Flags: ignoreversion recursesubdirs

Tudo o que estiver na pasta “C:programa” será copiado para a pasta da aplicação (seja ela qual for, dado o uso da constante {app}, que retornará o caminho do seu programa no sistema dos usuários). Para incluir as subpastas e tudo o que existir dentro delas também, é necessário adicionar a flag recursesubdirs (note ela no final da linha acima).

Se você precisar copiar arquivos para outros lugares, como a pasta do Windows, por exemplo, pode deixá-los numa pasta separada (fora da “C:programa”, no exemplo) e incluir uma nova entrada na seção [Files], para o novo arquivo:

Source: “C:teste.dll”; DestDir: “{win}”; Flags: ignoreversion

As constantes de pastas retornam o caminho correto da pasta no sistema do usuário, independente do idioma do Windows ou da partição em que ele estiver instalado. Você pode usá-las na seção [Files] e em uma série de outras, como na [Icons] ou na [Run]. A pasta padrão do seu programa fica dentro da Arquivos de programas, um local útil para guardar os programas. Se você quiser escolher outro local, troque o valor da diretiva DefaultDirName na seção [Setup]:

DefaultDirName={pf}Meu programa

Para a maioria das instalações, não é necessário alterar esse caminho. O instalador gravará no registro (na mesma chave de desinstalação) o caminho em que for instalado, e caso uma nova versão do programa for instalada, ele manterá a pasta existente como padrão.

Ele detecta se o programa já está instalado ou não com base no valor da diretiva AppId, ID da aplicação, na seção [Setup]. Quando você fizer uma nova versão do seu programa, que não puder ser entendida como uma atualização da atual (ou que possa coexistir com ela no sistema), altere o valor da AppId. Mas não faça isso se você pretende que o programa seja atualizável, por exemplo, da versão 1.2 para 1.5. É bom escolher um nome para a AppId que só o seu programa use, e seus programas diferentes também deverão usar IDs diferentes.

Uma outra recomendação minha é manter o arquivo de projeto numa pasta, e dentro dessa pasta a pasta com os arquivos do programa a serem inclusos. Exemplo de estrutura:

instalador.iss

leiame.txt

licença.txt
pasta_de_arquivos_do_programa

Assim, dentro do arquivo .iss você pode referenciar os arquivos usando caminhos relativos, como por exemplo:

[Files]

Source: “pasta_de_arquivos_do_programa*”; DestDir: “{app}”; Flags: ignoreversion recursesubdirs

Se precisar mover a pasta de lugar, leve tudo junto com ela. Dessa forma você não precisará editar o arquivo para retirar a referência estática, como C:pasta, por exemplo.

Criação de atalhos no menu Iniciar

A criação de atalhos pode ser configurada na seção [Icons]. Tem esta sintaxe:

[Icons]

Name: “{group}Meu Programa”; Filename: “{app}MeuPrograma.exe”

O parâmetro “Name” recebe o caminho do atalho, sem precisar colocar a extensão .lnk. Por padrão, o Inno Setup cria uma subpasta do menu “Iniciar > Programas”. É útil quando você instala vários atalhos, no mesmo grupo de programa (ou se quiser separar um grupo de atalhos para a sua empresa, e dentro dela colocar os atalhos dos programas). Esse caminho pode ser alterado por padrão na diretiva DefaultGroupName, da seção [Setup].

Agora, se seu programa só vai instalar um atalho (por exemplo, um navegador, ou um editor de textos), é recomendável que ele fique direto no “Iniciar > Programas”, economizando o caminho para o usuário. Para isso, basta alterar a entrada na seção [Icons], deixando-a assim:

[Icons]

Name: “{commonprograms}Meu Programa”; Filename: “{app}MeuPrograma.exe”

A constante {commonprograms} retorna o caminho da pasta que guarda os atalhos do menu Iniciar, comum para todos os usuários. A {userprograms} retorna o caminho da mesma pasta, mas sob o perfil do usuário. É recomendável usar a primeira. Se o usuário que instalar o programa não possuir direitos administrativos, então a pasta correspondente do perfil dele será usada automaticamente, em vez da pasta global.

Os atalhos serão excluídos na desinstalação apenas se o instalador os criar (ou se uma versão anterior do seu programa os tiver criado, mantendo a mesma AppId). Mas nada impede que você exclua arquivos ou atalhos na desinstalação, como vou comentar mais à frente.

Criando chaves no registro

A criação de chaves no registro durante a instalação pode ser feita com a função [Registry]. Algumas flags especiais devem ser usadas nas chaves que o seu programa criar, para que elas possam ser removidas automaticamente na desinstalação. Já nas chaves públicas ou do Windows, em que o seu programa simplesmente alterar alguns valores, tenha cuidado: nunca use a flag para remoção na desinstalação.

As entradas da seção [Registry] têm basicamente esta sintaxe:

[Registry]

Root: HKCU; SubKey: ChaveSubchave; ValueType: TipoDoValor; ValueName: NomeDoValor; ValueData: DadoDoValor;

O parâmetro Root define a chave root do registro que será alterada. Você deve colocar HKCU para a HKEY_CURRENT_USER, ou HKLM, para a HKEY_LOCAL_MACHINE (entre outras). No SubKey, defina o caminho desejado. Ele não precisa existir no sistema. Se não existir, será criado automaticamente. Por exemplo, “SoftwareMinha EmpresaMeu Programa”. Lembre-se de colocar textos que contenham espaços entre aspas. Em ValueType, defina o tipo do valor, que pode ser dword (inteiro), string (os mais usados), entre alguns outros. Para valores booleanos, use dword, e atribua ao valor 1 para True, ou 0 para False. Em ValueData, como era de se esperar, coloque o dado do valor. Se for uma string, prefira colocar entre aspas. Um exemplo:

Root: HKCU; SubKey: “SoftwareMinha EmpresaMeu programa”; ValueType: dword; ValueName: UsarCoresPersonalizadas; ValueData: 1;

Isso colocaria o valor 1 neste local:

HKEY_CURRENT_USER Software Minha Empresa Meu programa, valor dword “UsarCoresPersonalizadas”, com o valor 1. Outro exemplo, agora com uma string, que uso num dos meus programas:

Root: HKCU; SubKey: “SoftwareMepMep Texto”; ValueType: string; ValueName: Skin; ValueData: “{app}skins_Default Mep Texto 5.skn”;

Repare que você pode usar constantes do Inno Setup no valor, se precisar, para usar caminhos de pastas ou arquivos que variam de sistema para sistema – como no caso, usei a {app} para retornar a pasta da aplicação, já que queria referenciar um arquivo dentro dela.

Apesar de não ser necessário seguir a ordem no script do Inno para as chaves do registro, uma organização sempre faz bem. Por experiências próprias com ele, sugiro criar as chaves definindo que elas deverão ser removidas após a instalação, e só depois de declarar isso, colocar as entradas que gravarão os valores propriamente ditos. Por exemplo:

Root: HKLM; SubKey: SoftwareEmpresa; Flags: uninsdeletekeyifempty

Root: HKCU; SubKey: SoftwareEmpresa; Flags: uninsdeletekeyifempty

Root: HKLM; SubKey: SoftwareEmpresaPrograma; Flags: uninsdeletekey

Root: HKCU; SubKey: SoftwareEmpresaPrograma; Flags: uninsdeletekey

Isso supondo que você grave as configurações do seu programa na chave HKEY_CURRENT_USER Software Empresa Programa. Caso você tenha vários programas da mesma empresa, pode guardar as configurações dos outros numa subchave da chave da empresa, que serão vistos pelo editor do registro do Windows como pastinhas:

a576794
Seguindo a forma exemplificada nas 4 linhas mais acima, você obtém um instalador mais “profissional”. Ele cria a chave para a empresa, se ainda não existir, e configura para removê-la na desinstalação apenas se estiver vazia (com o uso da flag uninsdeletekeyifempty). Após isso, cria a chave do programa, dentro da chave da empresa, e configura para remoção na desinstalação, mesmo se não estiver vazia (já que está removendo o programa, não teria porque manter a chave do registro dele). A flag uninsdeletekey faz com que a chave e todas as suas subchaves sejam removidas na desinstalação. Caso você tenha vários programas, eles nunca removerão as configurações dos outros, pois cada um terá sua própria chave, sob o nome da chave da empresa. Ao desinstalar o último programa desta empresa, é que a chave da empresa será removida. Antes disso, não, pois com o uso da flag uninsdeletekeyifempty para a chave da empresa, esta não será excluída se ainda existirem subchaves (provavelmente de seus outros programas). Uma dica é colocar na ordem exibida. Na desinstalação, o Inno Setup executa as funções correspondentes de baixo para cima no script, as primeiras entradas serão as últimas a serem tratadas na desinstalação.

Caso você não queira usar uma chave para a empresa (que pode ser o seu nome, o produtor do programa), pode então usar diretamente uma para o programa, ficando assim apenas:

Root: HKLM; SubKey: SoftwarePrograma; Flags: uninsdeletekey

Root: HKCU; SubKey: SoftwarePrograma; Flags: uninsdeletekey

Nota: exemplifiquei com o uso do mesmo caminho de chave sob a HKEY_LOCAL_MACHINE e HKEY_CURRENT_USER. Para guardar as configurações do usuário, sempre prefira a HKEY_CURRENT_USER, use a HKEY_LOCAL_MACHINE para guardar dados durante a instalação que deverão estar acessíveis para leitura por todos os usuários.

Nunca use o uninsdeletekey em chaves usadas por outros programas ou pelo Windows. E a definição das chaves que seu programa usará deve ser feita no projeto do programa, não apenas na hora da criação do instalador. Se seu programa irá criar novas chaves em outros locais depois de aberto, é uma boa incluí-las para remoção, bastando definir da forma acima, como se fosse criá-las, e usar as flags uninsdeletekey ou uninsdeletekeyifempty, dependendo da situação.

Associando arquivos ao seu programa

Um uso comum da seção [Registry] é a associação de arquivos ao seu programa, embora eu prefira usar alguma função diretamente dentro do programa – por poder ser chamada pelo usuário sem que ele precise realizar uma nova instalação. Ela pode ser feita pela chave HKEY_CLASSES_ROOT, e a sintaxe seria:

[Registry]

Root: HKCR; Subkey: “.myp”; ValueType: string; ValueName: “”; ValueData: “MyProgramFile”; Flags: uninsdeletevalue

Root: HKCR; Subkey: “MyProgramFile”; ValueType: string; ValueName: “”; ValueData: “My Program File”; Flags: uninsdeletekey

Root: HKCR; Subkey: “MyProgramFileDefaultIcon”; ValueType: string; ValueName: “”; ValueData: “{app}MYPROG.EXE,0”

Root: HKCR; Subkey: “MyProgramFileshellopencommand”; ValueType: string; ValueName: “”; ValueData: “””{app}MYPROG.EXE”” “”%1″””

Onde:
.myp é a extensão desejada;

MyProgramFile é o nome interno do tipo de arquivo, use um diferente para cada extensão;

My Program File é a descrição dos arquivos desse tipo, que aparecerá no Windows Explorer;

{app}MYPROG.EXE,0 define o ícone dos arquivos, que poderá estar em um executável ou DLL (devendo ser seguido do índice) ou indique diretamente um arquivo .ico;

Tome cuidado aqui: “”{app}MYPROG.EXE”” “”%1″”. É desse jeito, use as aspas duplas e duplicadas, e cuidado com o espaço antes do “”%1″”. A string final deverá ficar assim:

“C:Arquivos de programasMYPROG.EXE” “%1”

Como as aspas são usadas internamente pelo Inno, é necessário usá-las duas vezes seguidas, “”, para que sejam gravada no registro uma única aspa.

Dica: ao modificar as associações de arquivos na instalação, inclua a diretiva ChangesAssociations=yes na seção [Setup]. Com ela, o instalador notifica o Windows para que recarregue as configurações de associações de arquivos no Explorer ao final da instalação.

Ao associar arquivos ao seu programa, tenha em mente que o mesmo deverá estar programado para abrir arquivos passados como parâmetro pela linha de comando. Caso contrário, ao dar um duplo clique num arquivo da extensão escolhida, o seu programa até será aberto, mas sem fazer nada – sem abrir o arquivo.

Lembre-se que você pode consultar a ajuda do Inno Setup (ou a ajuda on line do Mep Installer, que está em português) para ver as outras opções possíveis.

Execução de programas ao final da instalação ou desinstalação

Comum em muitos programas de instalação, pode ser útil rodar programas no final da instalação ou antes da desinstalação. Para isso existem as seções [Run] e [UninstallRun]. A sintaxe básica delas não têm segredo, e compartilham muitas propriedades. A Run roda programas ao final da instalação, antes de concluí-la, e a UninstallRun, antes da desinstalação começar.

Um exemplo:

[Run]

Filename: {app}Programa.exe; Parameters: /teste; StatusMsg: “Testando o programa”

A mensagem no StatusMsg é opcional, e pode ser declarada para aparecer durante a instalação, enquanto o instalador termina. Se nada for informado, ficará a mensagem padrão “Concluindo instalação”. Com as flags você pode configurar diversas coisas, como ocultar a janela do instalador ao rodar o comando, rodar o comando oculto (não faça isso para programas que exijam interação do usuário, senão o instalador vai ficar parado e o programa não seria mostrado :p), etc.

São vários os parâmetros, há uma lista na ajuda que comentei, do Mep Installer:

http://www.mephost.com/software/help/mpist14/secao_run.htm

Antes da desinstalação é a mesma coisa, use apenas dentro da [UninstallRun].

Excluindo arquivos na desinstalação ou instalação

Por padrão, o instalador do Inno Setup exclui apenas arquivos que ele tenha criado. Se seu programa criar pastas ou arquivos depois de instalado, estes permanecerão no sistema do usuário. Algumas vezes podem ser arquivos INI, que ficam na pasta da aplicação (inadequado hoje em dia, visto que os usuários limitados não podem gravar nada na pasta Arquivos de programas, mas muitos “programadores” insistem em usar isso, em vez de guardar o INI numa pasta sob o perfil do usuário). Seja qual for o caso, ao desinstalar seu programa a pasta dele poderá permanecer no sistema do usuário – o que é um tanto “chato” e incômodo.

Com a seção [UninstallDelete], você pode excluir pastas ou arquivos, durante a desinstalação. Você até pode colocar a pasta da sua aplicação, e excluir ela inteira. Mas isso não é uma boa idéia. Simples: se o usuário instalar o programa em outro lugar, por engano (como na pasta Documentos), ao desinstalar, a pasta toda iria pro saco. O meio mais “correto” seria incluir na seção [UninstallDelete] apenas arquivos que você saiba que seu programa poderá criar, e que deverão ser removidos. Exemplo:

[UninstallDelete]

Type: files; Name: {app}Programa.ini

Type: files; Name: {app}teste.txt

Type: filesandordirs; Name: {app}temporarios

Defina files no parâmetro Type para excluir arquivos, e filesandordirs para excluir arquivos ou pastas (incluindo subpastas e tudo o que existir dentro delas).

Em outras situações, pode ser necessário remover algum arquivo durante a instalação. Um exemplo é quando uma nova versão do seu programa não usa mais um arquivo que uma versão anterior usava. Seria bom removê-lo 🙂

Basta usar a [InstallDelete], e a sintaxe das entradas se mantém a mesma da [UninstallDelete].

Protegendo e criptografando o instalador com uma senha

O Inno Setup pode proteger a instalação com uma senha, é uma medida de “segurança” básica. A senha não é a mesma coisa de um número serial, apesar de ter função parecida: sem ela, não será possível continuar a instalação. É simples, basta definir a diretiva Password na seção [Setup]:

Password=teste

A tela que pede a senha para o usuário será assim:

m3789431a
A senha não será gravada no arquivo diretamente, mas sim um hash (sombra) dela. Os arquivos, o conteúdo do instalador em si, não estarão “protegidos”: eles não são encriptados por padrão. Você pode forçar uma encriptação usando a diretiva Encryption, ativando-a com “yes” na seção [Setup]:

Password=teste
Encryption=yes

Para isso, uma DLL com a função de criptografia do Inno deverá ser colocada na pasta do Inno Setup. Ele não inclui o suporte “nativo” à criptografia devido a legislação de alguns países. Basta baixar a DLL em:

http://www.jrsoftware.org/isdl.php

E colocá-la na pasta do Inno (normalmente Arquivos de programas Inno Setup). Não se preocupe em redistribui-la com o seu programa, não será necessário. Com a criptografia ativada, o conteúdo do instalador será codificado usando como base a senha escolhida, e então o arquivo estará protegido (mesmo que alguém consiga acesso ao pacote de dados dentro do instalador – o que não é difícil, visto que o Inno Setup é open source – não poderá fazer nada com os arquivos, pois estarão criptografados).

Protegendo com um número serial

A proteção por número serial é um recurso possível no Inno Setup, mas não “diretamente”. Com a diretiva UserInfoPage=yes na seção [Setup], ele mostra uma tela para digitação de um nome de usuário e organização. Mas não um número serial. O nome e a organização poderão ser recuperados com as constantes {userinfoname} e {userinfoorg}, podendo ser gravados no registro, num arquivo INI ou então passados como parâmetro para algum programa (usando a seção [Run], deixando a constante {userinfoname} ou {userinfoorg} como parâmetro para o seu executável).

Para que apareça o campo de número serial, você deverá usar a seção [Code]. O Inno Setup, a partir da versão 4, permite a codificação usando o Pascal Script. É uma linguagem de script baseada em Pascal, muito parecida com o Delphi. Você pode “programar” dentro do Inno, executar funções personalizadas em algumas situações e inclusive chamar funções em DLLs – suas ou não.

A seção [Code] é um pouco complexa para entender de imediato, ela contém funções e rotinas próprias que se aplicam apenas ao Inno Setup, assim como contém funções comuns a outros ambientes (principalmente ao Delphi; a saber, o Inno Setup é feito em Delphi). Para verificação de número serial, você deve criar a seção [Code] no script do Inno, e colocar a função CheckSerial. Esta função tem esta sintaxe:

function CheckSerial(Serial: String): Boolean;

O que ela faz? Ela recebe o serial preenchido pelo usuário, que é passado como string, e deve devolver um valor booleano (sim ou não), para liberar ou não a instalação. Para implementá-la, coloque no final do arquivo de script do Inno Setup:

[Code]

function CheckSerial(Serial: String): Boolean;

begin
end;

Entre o begin e o end você pode fazer literalmente o que quiser, como se estivesse num ambiente de programação. As funções internas providas com o Inno Setup são básicas, mas você poderá chamar DLLs, como explico já já.

Para validar o serial rapidamente, você poderia colocar:

function CheckSerial(Serial: String): Boolean;

begin
if Serial = ‘123456’ then

Result := True

else
Result := False;

end;

Isso limita a instalação ao serial “123456”. Experimente compilar o instalador e testar 🙂

m5561ab69
Não se esqueça de ativar a tela de informações do usuário, colocando UserInfoPage=yes, na seção [Setup].

Se você quiser, pode implementar um pouco mais, e testar também o nome de usuário e a organização preenchidos. Para isso, precisará usar variáveis e a função ExpandConstant, que expande uma constante do Inno, retornando o valor dela como string:

function CheckSerial(Serial: String): Boolean;

var

usu, org: String;

begin
usu := ExpandConstant(‘{userinfoname}’);

org := ExpandConstant(‘{userinfoorg}’);

if (usu = ‘Marcos’) and (org = ‘Guia do Hardware’) and (Serial = ‘123456’) then

Result := True

else
Result := False;

end;

Coloquei assim por motivos didáticos, nada impede que você simplifique a verificação do if, deixando-o apenas assim:

Result := (usu = ‘Marcos’) and (org = ‘Guia do Hardware’) and (Serial = ‘123456’);

Uma observação importante no Inno Setup, é que esta função é chamada para cada caractere que o usuário digitar. Se você inventar algum algoritmo de verificação diabólico que coma muito processamento, a digitação do serial pelo usuário ficará “lenta”. Ele chama a função ao digitar, pois libera o botão “Avançar” apenas se a informação estiver correta. Enquanto a função CheckSerial retornar False, o botão Avançar fica desativado.

Nada impede que algum “hacker” manipule o estado do botão Next do Inno Setup, usando aplicações de terceiros, e parta para a próxima tela sem digitar o número serial. O recurso é interessante, mas deve ser usado com cuidado. O Inno é um projeto aberto, suas especificações são claras e qualquer um munido de conhecimentos avançados pode manipular a função CheckSerial para sempre retornar True. A recomendação seria usar um sistema de registro externo ao Inno, com um algoritmo criado por você, e talvez usar o campo de serial apenas para a inserção do serial e posterior processamento – algo que pode ser útil dado o visual do instalador, ficaria mais “tradicional” solicitar o número serial durante a instalação. Uma proteção maior pode se dar usando a senha com criptografia ativada, como comentado mais acima – onde mesmo se o “hacker” burlar o sistema e conseguir avançar, os arquivos estarão altamente corrompidos sem a senha certa, e não servirão para nada.

Integração com DLLs: um exemplo prático

Uma das grandes vantagens do Inno Setup é a liberdade de programação. Com o Pascal Script, você pode usar uma série de funções para fazer uma infinidade de coisas. As funções inclusas com o Inno constam na ajuda dele, vale a pena dar uma conferida. E para as que não estão, você pode usar funções de DLLs, sejam estas suas ou não.

Vou dar um exemplo ainda na função CheckSerial, onde o algoritmo de verificação do número serial fica numa DLL. Há outras funções do Inno que são executadas em outras situações, como ao avançar nas telas de instalação, ao iniciar o instalador, ao finalizá-lo, ao copiar arquivos, etc.

Para usar funções de DLL, você precisa declará-las, assim:

function ValidaReg(usu, org, serial: String): Boolean;

external ‘ValidaReg@files:CheckSerial.dll stdcall’;

O primeiro nome ValidaReg escolhido pode ser um nome qualquer, será o nome da função importada dentro do programa – dentro do instalador. Ela receberá três parâmetros: o nome do usuário, organização e número serial preenchidos. E deverá retornar um valor booleano, True para liberar a instalação, ou False para negá-la.

Na segunda linha, fica indicado que a ValidaReg está na DLL CheckSerial.dll (que poderia ser qualquer outra). Mas onde estará esta DLL no sistema do usuário?

Você deve incluí-la no instalador, na seção [Files], com a flag especial dontcopy:

[Files]

Source: “CheckSerial.dll”; Flags: dontcopy

Essa flag faz que o arquivo indicado não seja copiado para a pasta da aplicação. Ele ficará numa pasta temporária que o Inno Setup cria durante a instalação, e a remove assim que a instalação é concluída.

Declarada a função da DLL, você pode usá-la no código da seção [Code], como se fosse uma função nativa do Inno. No caso da verificação do número serial, mudaríamos o código para isso:

function CheckSerial(Serial: String): Boolean;

var

usu, org: String;

begin
usu := ExpandConstant(‘{userinfoname}’);

org := ExpandConstant(‘{userinfoorg}’);

Result := ValidaReg(usu,org,Serial);

end;

Ou seja, quem determinará o resultado (True ou False) deixa de ser um verificador diretamente nesta função, sendo a função ValidaReg na DLL. Aqui está um exemplo da integração do Inno Setup com uma DLL. A criação de DLLs foge ao objetivo deste artigo, mas para que possa ser concluído, você precisará criar uma DLL de exemplo.

Em Delphi, você poderia simplesmente criar um arquivo .dpr com este conteúdo, e compilá-lo, que já teria a DLL que exporta a função ValidaReg:

library CheckSerial;

uses

Windows;
function ValidaReg(usu, org, serial: String): Boolean; stdcall;

begin
if (usu=’Marcos’) and (org=’Mep’) and (serial=’123-456-789′) then

Result := True

else
Result := False;

end;
exports ValidaReg;

begin
end.

Dentro da DLL você pode programar como quiser, aí fica a seu critério. A validação do número serial deve usar algum algoritmo criado por você, e claro, com algum sistema gerador de seriais com base no nome de usuário que só você possua. Não se esqueça que as DLLs interagem com os arquivos independentemente da linguagem em que foram criados (Delphi, C++, VB, etc), já que elas são compiladas.

A integração com DLLs do Inno Setup é muito boa e estável, e permite que ele dê conta de coisas que muitos instaladores comerciais não fazem.

Concluindo

Eis um pouco do Inno Setup. Ele ainda pode ser personalizado, de várias formas: além do uso de DLLs, é possível adicionar páginas (telas de instalação) personalizadas, para obter dados adicionais do usuário durante a instalação. Ou você pode ir mais longe, baixando o código fonte do Inno e alterando diretamente os arquivos do instalador – o que não é fácil, mas pode ser uma experiência interessante. Ele foi feito em Borland Delphi, e é compilado pelo Jordan Russell no velho Delphi 2 – já que as versões antigas do Delphi geram executáveis bem pequenos, perto das versões recentes 😉

Se você não gosta de manipular o script diretamente, pode experimentar o ISTool, uma interface gráfica para o Inno Setup, que permite criar e modificar os arquivos .iss facilmente:

m150edd86
Ele e várias outras utilidades podem ser baixados na página de downloads do Inno:

http://www.jrsoftware.org/is3rdparty.php

Bom trabalho 🙂

Sobre o Autor

Redes Sociais:

Deixe seu comentário

X