terça-feira, outubro 28, 2008

NSIS - parte 5

O NSIS é uma ferramente bastante rica, permitindo expansões de diversas formas. Melhor ainda, ela tem um recurso de macros que possibilita usar estas expansões de uma forma muito fácil. Por exemplo, usamos na parte anterior a Modern User Interface simplesmento usando um !include e meia dúzia de !insertmacros. Por trás disso tem muitas centenas de linhas de script (veja em C:\Program Files\NSIS\Contrib\Modern UI e C:\Program Files\NSIS\Contrib\Modern UI).

Uma coisa comum nas duas versões da Modern User Interface é a criação de novas páginas para o instalador, recurso este que pode ser usado diretamente nos nossos scripts. A versão 1 da MUI usa o recurso de Install Options. Este recurso, que já está sendo descontinuado, utiliza um arquivo .INI para definir os controles presentes na tela e para interagir com eles.

Vamos dar uma olhada neste post no recurso nsDialogs, usado pela MUI2. No nsDialogs a criação e interação com os controles é feita através de código, o que é mais flexível (e trabalhoso) que os arquivos .INI do Install Options.

Tanto Install Options como nsDialogs utilizam plugins, que são DLLs preparadas de acordo com algumas convenções do NSIS. De forma (quase) transparente para nós o NSIS coloca a DLL dentro do instalador, a expande em um diretório temporário e a apaga quando não for mais necessária.

Vejamos abaixo um exemplo e depois vamos análisar as linhas relevantes:

#
# Exemplo de uso do "nsDialogs" no NSIS
#

!include MUI2.nsh
!include nsDialogs.nsh
!include LogicLib.nsh


Name "Opções"
OutFile "InstOpc.exe"
InstallDir "$PROGRAMFILES\NSIS_Opcoes"
InstallDirRegKey HKLM "Software\NSIS_Opcoes" "Install_Dir"

BrandingText "DQSoft - http://dqsoft.blogspot.com"

Var ChaveUninstall
Var Dialog
Var Label
Var Text
Var Info


;--------------------------------
; Acrescenta um logotipo

!define MUI_HEADERIMAGE
!define MUI_HEADERIMAGE_BITMAP "dqsoft.bmp"
!define MUI_HEADERIMAGE_UNBITMAP "dqsoft.bmp"

;--------------------------------
; Instalador

!insertmacro MUI_PAGE_WELCOME
Page custom nsDialogsPage nsDialogsPageLeave
!insertmacro MUI_PAGE_DIRECTORY
!insertmacro MUI_PAGE_INSTFILES
!insertmacro MUI_PAGE_FINISH

!insertmacro MUI_UNPAGE_CONFIRM
!insertmacro MUI_UNPAGE_INSTFILES

!insertmacro MUI_LANGUAGE "PortugueseBR"


Section "-Obrigatoria"
StrCpy $ChaveUninstall "Software\Microsoft\Windows\CurrentVersion\Uninstall\DQSoft_Opcoes"
SetOutPath $INSTDIR

FileOpen $0 $INSTDIR\texto.txt w
FileWrite $0 $Info
FileClose $0


WriteRegStr HKLM SOFTWARE\NSIS_Opcoes "Install_Dir" "$INSTDIR"
WriteUninstaller "uninstall.exe"
WriteRegStr HKLM $ChaveUninstall "DisplayName" "NSIS Opcoes (remoção)"
WriteRegStr HKLM $ChaveUninstall "UninstallString" '"$INSTDIR\uninstall.exe"'
WriteRegStr HKLM $ChaveUninstall "DisplayIcon" '"$INSTDIR\uninstall.exe"'
WriteRegStr HKLM $ChaveUninstall "DisplayVersion" "1.0.0"
WriteRegStr HKLM $ChaveUninstall "Publisher" "DQSoft"
WriteRegStr HKLM $ChaveUninstall "UrlInfoAbout" "http://dqsoft.blogspot.com"
SectionEnd

Section "Atalhos no Menu Iniciar"
CreateDirectory "$SMPROGRAMS\NSIS Opcoes"
CreateShortCut "$SMPROGRAMS\NSIS Opcoes\Texto informado.lnk" "$INSTDIR\texto.txt"
CreateShortCut "$SMPROGRAMS\NSIS Opcoes\Remove.lnk" "$INSTDIR\uninstall.exe"
SectionEnd

;--------------------------------
; Nossa página personalizada

Function nsDialogsPage

nsDialogs::Create /NOUNLOAD 1018
Pop $Dialog

${If} $Dialog == error
Abort
${EndIf}

${NSD_CreateLabel} 0 0 100% 12u "Texto a gravar:"
Pop $Label

${NSD_CreateText} 0 13u 100% -13u "Digite aqui..."
Pop $Text

nsDialogs::Show

FunctionEnd

Function nsDialogsPageLeave

${NSD_GetText} $Text $Info

FunctionEnd

;--------------------------------
; Desinstalador

Section "Uninstall"
StrCpy $ChaveUninstall "Software\Microsoft\Windows\CurrentVersion\Uninstall\DQSoft_Opcoes"
Delete "$INSTDIR\*.*"
RMDir "$INSTDIR"
Delete "$SMPROGRAMS\NSIS Opcoes\*.*"
RMDir "$SMPROGRAMS\NSIS Opcoes"
DeleteRegKey HKLM SOFTWARE\NSIS_Opcoes
DeleteRegKey HKLM $ChaveUninstall
SectionEnd
O primeiro ponto a reparar é os vários !include no início:
  • MUI2.nsh para usarmos a Modern User Interface
  • nsDialogs.nsh para criarmos a nova página
  • LogicLib.nsh define algumas operções lógicas que vamos usar
No meio das declarações das páginas do instalador temos a nossa página personalizada:

Page custom nsDialogsPage nsDialogsPageLeave
A página personalizada envolve duas funções que declarmos adiante, uma executada antes da execução (que irá criar a página) e outra executada quando o operador sai da página (que usaremos para pegar os valores fornecidos).

Na nossa sessão obrigatória, ao invés de instalarmos a calculadora, vamos criar um arquivo texto contendo um texto que foi digitado na nossa página personalizada. Reparar que o NSIS possui instruções também para manipular arquivos (no caso estamos usando FileOpen, FileWrite e FileClose).

Chegamos agora à função que ira criar a nossa nova página. A notação nsDialogs::xxxx indica a chamada de uma rotina na DLL nsDialogs. A primeira rotina chamada é Create, que irá criar o diálogo. A opção /NOUNLOAD indica que vamos continuar usando a DLL e portanto ela não deve ser descarregada (é este o motivo de eu ter dito que o uso da DLL era quase transparente). O número mágico que segue, 1018, indica a página que vamos sobrepor. A documentação do nsDialogs informa os números apropriados.

O resultado do Create é um handle para o diálogo (uma identificação para nos referirmos a ele posteriormente). Como acontece em vários locais no NSIS, o resultado fica em uma pilha e precisamos fazer um POP para recuperá-lo e salvá-lo em uma variável. Por segurança, testamos se o valor retornado é válido.

Em seguida criamos dois controles no diálogo: um label (texto estático) e um textbox (caixa para entrada de texto). Os quatro números presentes indicam a posição inicial e o tamanho. Como pode ser visto, existem várias opções de fazer isto: 0 é um posição absolutam em pixels; 12u é um valor proporcional ao tamanho do diálogo (que por sua vez depende do tamanho do fonte do sistema) e 100% é um valor relativo ao tamanho total do diálogo. Além de label e text, existem vários outros controles que podem ser usados.

A rotina de saída da página usa a macro GetText para recuperar o conteúdo da caixa de entrada de texto e salvá-lo em uma variável.

A nossa página personalizada fica com o seguinte aspecto:


Uso Prático

Ok, muito interessante, mas para que pode servir? O uso mais comum é para solicitar informações adicionais ao operador, configurando o software durante a instalação. Embora este exemplo tenha gravado a informação em um arquivo texto, existem instruções no NSIS para escrever no Registry (como já vimos) e para escrever em arquivos .INI.

Alguns exemplos de informações que já solicitei em meus instaladores:
  • nome de um diretório que será usado para interface entre o meu programa e uma outra aplicação
  • dados para acesso a uma base de dados
  • endereço IP de um servidor
No próximo post farei um apanhado geral de vários recursos menores do NSIS.

4 comentários:

Felipe Carvalho disse...

Realmente muito bom!!!!

Me ajudou muito!!!

Estou à espera de mais informação.....

Obrigado pelo tutorial muito bem escrito!

Parabéns

Ricardo disse...

Seu tutorial é muito bom, mas preciso de uma ajuda, preciso criar um desistalador que pergunte se eu quero desinstalar o programa ou reparar, mas estou com muita dificuldade, vc poderia fornecer uma explicação de como fazer isso ???

Felipe Carvalho disse...

Poxa.... pq não continuo a série??

Muito bom... me ajudou muito! Mas chegou até um momento que tive que ir a luta sozinho.

Mas sempre passo aqui pra ver se tem mais alguma coisa para ser acrescentado. ^^

Vlw!

Daniel Quadros disse...

Felipe,

Fico feliz em ter ajudado. Pessoalmente não fiquei 100% feliz com o resultado, queria ter achado uma ordem melhor para apresentar as coisas, o post seguinte estava ficando muito deslocado do resto.

Mas não desisti, está na lista retomar este assunto.

[]