Depois de meses trabalhando naquele app que o cliente pediu, finalmente ele está pronto para que o cliente o veja e dê sua opinião.

Isso, em qualquer outro tipo de projeto Windows seria fácil: um site ou aplicativo Silverlight é só questão de publicar em um servidor qualquer, um aplicativo Windows Forms ou WPF é só criar um click-once e o cliente já pode começar a criticar… quero dizer, apreciar o bom trabalho que você fez no aplicativo que ele pediu.

Mas, e em se tratando de um aplicativo Windows 8?

É inviável (e às vezes até impossível) publicar um aplicativo na Windows Store só para que o cliente o veja (para quem trabalha com Scrum por exemplo, vai entregar o app em pedaços até a última sprint). O jeito é fazer o tão conhecido “sideloading”, que consiste em alterar um monte de configurações do Windows, rodar um script Powershell, se autenticar na Windows Store para obter uma licença de developer até que enfim o aplicativo é instalado (somente para o administrador da máquina) para que o cliente possa ver.

Não seria melhor criar um setup.exe, onde o cliente clica em Próximo, Próximo, Concluir e o app simplesmente aparece no Menu Iniciar? Este post é justamente sobre como fazer isso.

Ferramentas necessárias

Sempre achei as ferramentas de setup do Visual Studio demasiadamente complicadas (ainda mais agora, no VS 2012 que só tem suporte para InstallShield Lite), mas, temos uma alternativa muito boa (inclusive para outros tipos de projeto): o INNO Setup.

O INNO Setup é um instalador feito em Pascal (então não há a necessidade de se ter instalado nenhum tipo de dependência na máquina, como o .net framework) que, através de um script (algo parecido com um arquivo .INI), pode realizar instalações simples ou até mesmo instalações super complexas (inclusive com suporte para scripts em Pascal).

O primeiro passo é puxar o compilador do Inno Setup (que nada mais é do que um editor de textos onde iremos escrever nosso script e pedir para ele transformar em um setup.exe): http://www.jrsoftware.org/isinfo.php

Clique no link Download Inno Setup e pegue a última versão (geralmente é o primeiro link encontrado na página, como mostra a imagem abaixo):

Após o download, basta instalá-lo utilizando o bom e velho Next, Next, Finish. Importante: em algum momento, o instalador irá perguntar se deseja instalar um componente extra sobre Inno Setup Preprocessor Directives. Permita esta instalação pois isso poderá ser muito útil caso deseje colocar o compilador do Inno Setup em uma tarefa de build automatizada (como o build do Team Foundation, por exemplo).

Para facilitar a criação do script (e até mesmo para você utilizar isso mais facilmente em outros tipos de instalações ou seguir as recomendações de melhorias que darei aqui), iremos instalar uma segunda ferramenta que é um editor visual para os scripts do Inno Setup. Sem ele, você irá ler muitas e muitas linhas de documentação para fazer o que quer.

A ferramenta visual está no mesmo site, no menu lateral esquerdo, sob o nome de Thirdy-Party Files (arquivos de terceiros). Clique neste link e em seguida procure por Inno Script Studio:

Da mesma forma, instale-o utilizando o Next, Next, Finish.

Empacotando seu aplicativo

Para realizar a instalação, precisamos empacotar o aplicativo em questão. Isso é feito facilmente no próprio Visual Studio: basta abrir o solução do seu projeto, selecionar o projeto dentro da solução referente ao Windows Store App, e utilizar o menu indicado abaixo:

Lembre-se: este menu é habilitado somente se no Solution Explorer, um projeto Windows Store App estiver selecionado! (Se o projeto atualmente selecionado for, por exemplo, uma biblioteca, este menu permanecerá desabilitado).

Ao clicar nesta opção, a seguinte janela será apresentada:

Basta selecionar a opção No (pois não estamos querendo criar um pacote que será submetido à Windows Store) e clicar em Next.

O pacote será criado na pasta especificada neste segundo passo no assistente. Guarde bem o local desta pasta pois precisaremos destes arquivos depois.

Abaixo, você pode selecionar uma ou mais arquiteturas de processadores, bem como o tipo de build (release ou debug). Quando utilizamos alguma biblioteca exótica, o aplicativo deixa de funcionar no modo Neutral (Any CPU) e, como estamos fazendo um instalador para um Windows “normal”, podemos descartar a arquitetura ARM (pois esta é utilizada apenas em Tablets).

Eu pessoalmente fecho os pacotes para testes em clientes em modo Release (para ficar um pouco mais rápido) e em x64 (a menos que o cliente especificamente peça um pacote para rodar em um destes híbridos com processador x86 ATOM). Fica a seu critério aqui (incluindo a opção de incluir símbolos públicos, o que pode auxiliar na depuração e logs para encontrar problemas quando o aplicativo os apresentar).

O Inno Setup poderia facilmente criar uma opção no instalador para que o usuário selecionasse se deseja x86 ou x64, mas, para um usuário leigo (nosso cliente), isso é uma informação inútil e acarretaria em um setup com o dobro do tamanho (uma vez que temos 2 releases sendo empacotados).

Ao clicar em Create, um build será invocado e, após concluído, seu pacote estará disponível na pasta especificada (e o assistente terminará com esta tela:)

Neste momento, você poderá apenas clicar em OK para fechar a janela ou iniciar o Windows App Certification Kit. Irei comentar sobre ele no futuro, mas, basicamente, é um sistema que realiza uma série de testes em seu aplicativo para certificar que alguns pontos que provocam rejeições pela Windows Store estejam OK. Vale a pena rodar isso ao fechar uma release para saber se está tudo bem e evitar ter que realizar muito trabalho quando enviar o seu aplicativo para a Windows Store e ele ser rejeitado por um detalhe simples.

Lembra do caminho que pedi para que lembrasse? Pois é. Nele estão todos os arquivos de instalação de seu aplicativo e são estes arquivos que iremos incluir no setup:

Criando o script

Localize em seu menu iniciar o Inno Script Studio e inicie-o. Basta pressionar a tecla Windows e digitar “script studio” e você o verá facilmente (mas você já sabia como utilizar este atalho do Windows 8, não é?)

Ao abrir o Inno Script Studio, a janela de novo projeto será aberta. Neste ponto, basta dar OK para iniciar:

Agora um assistente iniciará um script básico com algumas informações sobre nosso aplicativo.

Neste passo podemos incluir algumas informações sobre nosso aplicativo (é sempre bom ler a documentação do Inno Setup, pois este editor visual é bem resumido).

Este passo é importante: um aplicativo Windows 8 deve ser instalado em uma pasta especial (e, na verdade, nem é o Inno Setup que irá fazer isso). Neste caso especial, não queremos criar nenhum tipo de pasta em Arquivos de Programas, então devemos selecionar a opção O aplicativo não requer uma pasta.

Este passo serve para que você insira os arquivos que fazem parte do aplicativo, mas não iremos fazer isto neste momento. Basta clicar em Next para ir para o próximo passo.

Este é um passo interessante. Aqui, há 3 arquivos que podemos inserir como passos de nosso instalador para mostrar algumas informações para quem está instalando, como arquivo de licença (aqueles arquivos chatos que ninguém lê) e mensagens que podem ser inseridas antes e após a instalação do aplicativo.

Fica ao critério do desenvolvedor colocar o que desejar aqui (ou até mesmo ignorar isso). Eu pessoalmente colocaria um termo de uso (coisas como não fornecer o instalador a terceiros, estar ciente de que é uma versão beta, etc.).

Neste passo, podemos escolher uma ou mais línguas em que o instalador irá operar. No contexto atual (dar um pacote instalável de um app Windows 8 para um cliente), creio que utilizar português seja o mais apropriado, mas você pode escolher quantas línguas desejar aqui (o instalador irá perguntar ao usuário em qual língua quer que a instalação prossiga, você já deve ter visto este tipo de instalação inúmeras vezes).

Aqui podemos configurar onde nosso setup.exe será criado (Custom compiler output directory), o nome do instalador (setup irá gerar setup.exe) e podemos definir um ícone customizado e até mesmo proteger o setup com uma senha (para, por exemplo, certificar que apenas usuários com a senha possam instalar o aplicativo).

Lembra o pacote adicional sobre diretivas de pré-processamento que a instalação do Inno Setup nos perguntou? Ele serve para criar algo como variáveis, o que facilita a edição do script (por exemplo, supondo que o nome do aplicativo seja repetido diversas vezes dentro do script, podemos criar uma diretiva com o nome do aplicativo e utilizar esta referência em diversos pontos. Ao mudar a definição, não precisamos nos preocupar em mudar o restante do script). Isto funciona exatamente como constantes nas linguagens de programação (const em C#).

Depois de todo este processo, temos um script básico para criar nosso instalador:

Agora precisamos refinar este script e inserir nosso aplicativo empacotado. Fique à vontade em ler a documentação do Inno Setup e explorar as opções disponíveis, pois irei explicar aqui somente o básico para montarmos nosso instalador.

Clique na seção Files do Inno Script Studio e clique no botão New Item:

Escolha o único arquivo que está na pasta que você escolheu para o Visual Studio criar o pacote da sua aplicação (hrocesso, temos um script básico para criar nosso instalador:

Agora precisamos refinar este script e inserir nosso aplicativo empacotado. Fique à vontade em ler a documentação do Inno Setup e explorar as opções disponíveis, pois irei explicar aqui somente o básico para montarmos nosso instalador.

Clique na seção Files do Inno Script Studio e á um arquivo com extensão .appxupload e uma pasta com vários arquivos, selecione apenas o arquivo .appxupload).

Certifique-se de que o caminho de destino (onde o instalador irá “instalar” este arquivo) seja {tmp} (na verdade, iremos apenas copiar o pacote do aplicativo para uma pasta temporária, utilizar os mecanismos apropriados para instalá-lo no Windows e depois apagar este pacote, então os arquivos não ficarão instalados de fato na máquina destino).

Precisamos colocar aquela pasta que está junto com o arquivo .appxupload. Para não deixar o script muito grande e confuso, podemos adicionar todo o conteúdo da pasta com apenas uma linha. Infelizmente, este procedimento não é muito fácil de fazer visualmente, então, clique na seção Inno Setup Script e altere o seu script conforme a imagem abaixo (note que os nomes das pastas e do aplicativo obviamente diferem do meu script nesta imagem do que você está fazendo em sua máquina agora):

O que fizemos aqui foi incluir a seguinte linha na seção [Files] do script:

Source: "C:TempAppInstalavelAppInstalavelAppPackagesAppInstalavel_1.0.0.0_x64_Test*.*"; DestDir: "{tmp}AppInstalavel_1.0.0.0_x64_Test"; Flags: ignoreversion recursesubdirs createallsubdirs

Note que incluímos todos os arquivos e pastas do pacote, mas sem precisar criar uma linha para cada uma das pastas e arquivos, o que facilita a leitura e manutenção do script.

Agora temos que realizar uma configuração no Windows para que aplicativos possam ser instalados sem passar pela Windows Store. Normalmente, este passo implica em entrar como administrador e editar as políticas de segurança do Windows (usando o gpedit.msc). O instalador irá realizar a mesma função, mas alterando diretamente uma chave no registro do Windows.

O instalador poderá ser utilizado mesmo por usuários que não sejam administradores da máquina, porém, há ao menos 2 passos que requerem esta elevação, o que não é um grande problema, visto que agora (finalmente) o Windows pode elevar um usuário comum à administrador temporariamente. Quando um usuário comum tentar utilizar este instalador, o Windows irá mostrar uma janela pedindo a senha de um usuário administrativo (que é o seu usuário normal, mesmo que seja um usuário com autenticação via internet (live)).

Você pode, depois que este instalador rodar ao menos uma vez em uma máquina, remover estes passos que requerem acesso administrativo, pois eles apenas preparam o ambiente. Fica ao seu critério facilitar ao máximo a vida do usuário ou proceder da forma mais segura (e precisar de uma autenticação de um administrador durante a instalação).

Há um outro detalhe neste ponto: quando uma máquina está sob um domínio (via Active Directory), esta configuração de segurança fica no AD e não na máquina local. Neste caso, você deverá seguir os procedimentos normais de habilitação de instalação de aplicativos sem a Windows Store através do domínio (a documentação sobre isso encontra-se aqui: http://technet.microsoft.com/en-us/library/hh852635.aspx)

Para habilitarmos esta política de segurança no instalador, devemos criar ou alterar uma chave do registro do Windows (mais precisamente: HKEY_LOCAL_MACHINE\Software\Policies\Microsoft\Windows\Appx\AllowAllTrustedApps. Isso pode ser feito automaticamente pelo instalador (por isso a permissão administrativa) criando a chave na seção Registry do Inno Script Studio:

Esta linha de script se encarregará de criar a chave no registro para habilitar a política de segurança necessária. Certifique-se de clicar em createvalueifdoesntexist, pois esta chave não existe no registro do Windows caso a política nunca tenha sido alterada antes.

Só para fins de comparação, esta chave de registro habilita uma política de segurança que é possível monitorar e alterar utilizando o comando gpedit.msc, como abaixo:

Ou caso seu Windows esteja em português:

Agora precisamos criar dois arquivos batch para realizar duas funções separadas utilizando o PowerShell.

Em primeiro lugar, o PowerShell não executa scripts, por segurança. Aproveitando que estamos em um contexto de usuário elevado (administrador), vamos pedir ao PowerShell que libere esta função.

A razão dos dois scripts é que, caso a instalação do aplicativo ocorresse com o usuário administrativo, o aplicativo iria ser instalado somente para aquele usuário. O script que de fato instala o pacote no Windows 8 irá ser executado com o mesmo usuário que está autenticado na máquina (com as elevações administrativas removidas), permitindo assim que mesmo um usuário não administrativo possa rodar o aplicativo sem problemas.

Vamos então criar primeiramente um arquivo chamado PreparePS.cmd com o seguinte conteúdo:

<code class="language-bat">@Echo OFF
ECHO PREPARANDO AMBIENTE POWERSHELL
ECHO ==============================
CD %1
POWERSHELL -command set-executionpolicy unrestricted
ECHO Aguardando finalizacao do processo...
PING localhost &gt; NULL
</code>

Este comando, quando executado de forma elevada, remove as restrições de segurança de execução do PowerShell, executando o comando Set-ExecutionPolicy Unrestricted. (Maiores detalhes aqui: http://go.microsoft.com/fwlink/?LinkID=135170)

O segundo arquivo se chama RunPS.cmd e será o responsável por instalar o aplicativo de fato:

<code class="language-bat">@Echo OFF
ECHO INSTALANDO APLICATIVO
ECHO =====================
CD %1
POWERSHELL .Add-AppDevPackage.ps1
ECHO Aguardando finalizacao do processo...
PING localhost &gt; NULL
</code>

Aqui apenas executamos um script PowerShell que foram criados automaticamente pelo Visual Studio durante o empacotamento do aplicativo, junto com uma pequena pausa no final, caso algum erro ocorra.

Salve estes dois arquivos na mesma pasta do seu pacote (no mesmo nível do arquivo .appxupload) e arraste-o para dentro da seção Files do Inno Script Studio. Certifique-se de especificar como destino a pasta {tmp}, exatamente como foi feito para o arquivo .appxupload.

Agora vá até a seção Install Run e mande executar estes dois scripts com as configurações abaixo:

Preste atenção no Working Directory, que é o caminho da pasta temporária onde o script deverá ser executado e também na área roxa: o primeiro script roda como runascurrentuser, que significa rodar com o mesmo usuário que o instalador está utilizando (no nosso caso, um usuário administrativo elevado). O segundo script, no entanto, é importante rodar com o usuário originalmente autenticado na máquina (runasoriginaluser), afinal, estamos instalando o aplicativo para este usuário (e não para o administrador). Obviamente, se os dois usuários forem o mesmo, nada muda e tudo funciona normalmente.

Passos finais

Tudo já está praticamente pronto, só precisamos agora dos procedimentos de limpeza e algum refinamento para evitar que exista um desinstalador do nosso aplicativo (lembrando: o setup não irá de fato instalar nada, serve apenas como um suporte para instalar um aplicativo da forma mais fácil possível para um usuário comum).

Na seção Install Delete, inclua todos os arquivos que foram adicionados pelo instalador na pasta {tmp}, para que não fique nenhum arquivo do pacote sujando a pasta temporária do usuário:

E, finalmente, as opções finais do instalador (acessíveis no botão Setup Options na barra de ferramentas do Inno Script Studio):

Esta opção irá elevar o instalador ao ser executado (necessário para mudar a chave de registro e configurar as restrições de scripts do PowerShell).

Finalmente, esta opção irá restringir a criação do desinstalador do nosso aplicativo (porque, na verdade, não instalamos nada na máquina, apenas copiamos o pacote, instalamos via powershell e depois o excluímos).

Você pode também criar um desinstalador que execute o comando de remoção do aplicativo via PowerShell (Remove-AppxPackage NomeDoPacote) e que reverta as duas configurações de segurança que mudamos (uma no registro e outra no PowerShell). Com este editor visual, fica muito simples fazer isso.

O script final

Nosso script final ficou assim:

; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "App Instalável"
#define MyAppVersion "1.0"
#define MyAppPublisher "J.C.Ködel"
#define MyAppURL "http://kodel.com.br/"
#define MyAppExeName "MyProg.exe"

[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={{74CF4D5B-59B2-45E0-ADD2-91DB59AB90E0}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
CreateAppDir=no
OutputDir=C:UsersJCKodelDesktopAppInstalavel
OutputBaseFilename=setup
Compression=lzma
SolidCompression=yes
AllowCancelDuringInstall=False
Uninstallable=no

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

[Files]
Source: "C:TempAppInstalavelAppInstalavelAppPackagesAppInstalavel_1.0.0.0_x64.appxupload"; DestDir: "{tmp}"; Flags: ignoreversion
Source: "C:TempAppInstalavelAppInstalavelAppPackagesAppInstalavel_1.0.0.0_x64_Test*"; DestDir: "{tmp}Cinemark_1.0.2.20_x64_Test"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "C:TempAppInstalavelAppInstalavelAppPackagesRunPS.cmd"; DestDir: "{tmp}"; Flags: ignoreversion
Source: "C:TempAppInstalavelAppInstalavelAppPackagesPreparePS.cmd"; DestDir: "{tmp}"; Flags: ignoreversion

[Registry]
Root: "HKLM"; Subkey: "SoftwarePoliciesMicrosoftWindowsAppx"; ValueType: dword; ValueName: "AllowAllTrustedApps"; ValueData: "1"; Flags: createvalueifdoesntexist

[Run]
Filename: "{tmp}PreparePS.cmd"; WorkingDir: "{tmp}AppInstalavel_1.0.0.0_x64_Test"; Flags: waituntilterminated shellexec runascurrentuser; Description: "Instalando app"; StatusMsg: "Aguarde enquanto o aplicativo é instalado"
Filename: "{tmp}RunPS.cmd"; Parameters: "{tmp}AppInstalavel_1.0.0.0_x64_Test"; WorkingDir: "{tmp}AppInstalavel_1.0.0.0_x64_Test"; Flags: runasoriginaluser waituntilterminated shellexec; Description: "Instalando app"; StatusMsg: "Aguarde enquanto o aplicativo é instalado"

[InstallDelete]
Type: filesandordirs; Name: "{tmp}"

Compilando e Testando

Agora é só clicar no primeiro botão destacado na imagem acima para compilar o script e no segundo botão para iniciar o setup para testes.

O primeiro botão apenas envia este script para o compilador de linha de comando do Inno Setup (percebeu que podemos colocar aqui um passo em um MSBUILD para gerar um pacote automaticamente durante um build?).

O segundo botão apenas roda o setup.exe que está na pasta que você configurou (no meu caso, no Desktop).

Instalação

A instalação geral começa de forma muito familiar:

Depois dos arquivos copiados para a pasta temporária, o PowerShell assume. Você deve acompanhar o usuário na primeira instalação, caso ele não esteja acostumado ou confortável em utilizar um console para responder algumas perguntas:

Instalação

A instalação geral começa de forma muito familiar:

Depois dos arquivos copiados para a pasta uploads/2013/10/Install3.png">

Neste passo, o PowerShell irá instalar o certificado do aplicativo no armazém de certificados do Windows. O certificado é automaticamente criado pelo Visual Studio quando você cria um projeto Windows Store App, porém, é um certificado não reconhecido (também conhecido como self-signed certificate, o que significa que você mesmo está certificando que o aplicativo é válido, o que funciona somente em modo de desenvolvimento (daí aquela configuração de política de segurança para permitir a instalação de aplicativos com certificados inválidos)).

Note que aplicativos neste estado funcionam baseados em uma licença de desenvolvedor da Windows Store (exatamente a mesma que você utiliza para criar o aplicativo no Visual Studio). Certamente o seu cliente já está adiantado e já deu entrada na criação da conta da empresa na Windows Store e já tem um login live válido para obter uma licença de desenvolvedor. Caso não tenha feito isso, você poderá utilizar sua própria conta para obter uma licença de uso temporária para seu cliente (ou criar uma para ele):

E, finalmente (sério, finalmente mesmo desta vez), o PowerShell nos diz que tudo está OK e nosso aplicativo está instalado:

Aprimoramentos

Este script é um script bem simples que até pode ser utilizado para envios de releases para seus clientes, mas há muito o que fazer para aprimorá-lo e por isso é importante ler a documentação do Inno Setup, se familiarizar com o seu editor visual para criar uma experiência melhor para o usuário final.

Um dos aprimoramentos imediatos que pode ser feito facilmente é incluir o InnoSetup em seu processo de compilação (seja via MsBuild ou Team Foundation) para gerar o pacote automaticamente e disponibilizar isso em um FTP (ou mesmo versionado no TFS, que seu cliente tem acesso ao portal).

[Fonte: http://www.kodel.com.br/criando-instaladores-para-instalar-manualmente-windows-store-apps/]