NSIS Tutorial Teil 2

Einleitung

Nachdem wir im 1. Teil des Tutorials unseren ersten Installer erstellt hatten, werden wir in diesem Teil die installierten Dateien auch wieder entfernen. Zudem werden wir einige weitere Wizard-Seiten anschauen und dem Benutzer die Möglichkeit geben, bestimmte Teile der Installation auszuwählen.

Uninstall

Dem Benutzer die Möglichkeit zu geben, unsere Anwendung wieder zu entfernen gehört nicht nur zum guten Ton, sondern hat auch für uns Vorteile:

  • Für ein Update können die alten Dateien zuerst sauber entfernt werden. Somit gibt es keine Seiteneffekte durch alte Dateien, die eventuell für die neue Version nicht mehr benötigt werden.
  • Wenn der Benutzer ein Programm von uns, dass ihm nicht gefallen hat, nur mit viel Mühe wieder los wird, wird er kaum ein anderes Produkt von uns ausprobieren.

Um unseren Installer aus dem 1. Teil um einen Uninstaller zu ergänzen kopieren wir das Script für den „First Installer“ und ändern/erweitern ihn so dass er folgendermassen aussieht:

Name "Second Installer"

OutFile "secondinstaller.exe"
InstallDir $PROGRAMFILES\MySecondInstaller

Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles

Section ""
  SetOutPath $INSTDIR
  File C:\Windows\system32\notepad.exe
  WriteUninstaller $INSTDIR\uninstall.exe
SectionEnd

Section "Uninstall"
  Delete $INSTDIR\uninstall.exe
  Delete $INSTDIR\notepad.exe
  RMDir $INSTDIR
SectionEnd

Ausser dass wir den Namen in „Second Installer“ geändert haben sind drei Ergänzungen hinzugekommen:

UninstPage

Diese beiden Einträge geben an, dass für das Entfernen der installierten Dateien zwei Dialogseiten angezeigt werden sollen. Als erste die Bestätigungsseite, ob man wirklich die installierten Dateien entfernen will und als zweite die Seite, welche den Fortschritt des Deinstallierens anzeigt.

WriteUninstaller

Der Befehl WriteUninstaller schreibt die Routine für das Entfernen der Installation mit dem angegebenen Namen in den angegebenen Ordner.

Section "Uninstall"

Diese Section wird für das Entfernen der Installation aufgerufen. Als erstes wird der mit WriteUninstaller erzeugte Uninstaller entfernt. Danach wird die installierte Datei (notepad.exe) und zum Schluss das Installationsverzeichnis gelöscht.

Der Unistaller kann gelöscht werden, während er ausgeführt wird, da er zur Ausführung in das Temp-Verzeichnis des Systems kopiert wird.

Noch eine Anmerkung zur Variablen $INSTDIR. Diese enthält während der Deinstallation den Pfad, in dem sich der Uninstaller befindet. Falls man diesen mit WriteUninstaller z.B. in einen Unterordner „uninstall“ schreibt muss man dies während des Deinstallierens berücksichtigen, indem man die Pfade anpasst (z.B. $INSTDIR\..\notepad.exe).

Follow me

Vor der Installation möchte man dem Benutzer vielleicht noch mehr Informationen geben (Lizenzbedingungen) oder Angaben (Benutzer- und Firmenname) von ihm verlangen.

Um die Lizenzbedingungen anzuzeigen gibt es das Page license Kommando. Mit dem Attribut LicenseData wird die Datei angegeben, welche die Lizenzbedingungen enthält (im .txt oder .rtf Format). Das Attribut LicenseText erlaubt es, den Text der oberhalb des Lizenztextes angezeigt wird anzupassen.

Die Abfrage von Benutzername und Passwort benötigt etwas mehr Aufwand. Als erstes muss man den Dialog definieren, d.h. wo soll welches Element angezeigt werden. Dies kann mit HM NIS Edit komfortabel über einen grafischen Editor erfolgen. Als Resultat ergibt sich eine Datei mit folgendem Inhalt:

[Settings]
NumFields=5

[Field 1]
Type=Label
Text=Name
Left=16
Right=34
Top=32
Bottom=40

[Field 2]
Type=Text
Left=64
Right=188
Top=30
Bottom=42

[Field 3]
Type=Label
Text=Company
Left=16
Right=45
Top=48
Bottom=56

[Field 4]
Type=Text
Left=64
Right=188
Top=46
Bottom=59

[Field 5]
Type=Label
Text=Please enter your Name and your Company
Left=16
Right=196
Top=4
Bottom=21

Am einfachsten ist es, diesen Text zu kopieren und in eine neue Datei mit dem Namen namecompany.ini einzufügen. Die Datei sollte im selben Ordner liegen wie das Installer-Script.

Im Installer-Script gibt es einiges anzupassen, so dass es wie folgt aussieht:

Name "Third Installer"

OutFile "thirdinstaller.exe"
InstallDir $PROGRAMFILES\MyThirdInstaller

Page license
Page custom getUsername
Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles

LicenseData "license.txt"

Var UserName
Var Company

Function ".onInit"
  InitPluginsDir
  File /oname=$PLUGINSDIR\namecompany.ini "namecompany.ini"
FunctionEnd

Function getUsername
  Push $R0
  InstallOptions::dialog $PLUGINSDIR\namecompany.ini
  Pop $R0
  ReadINIStr $UserName "$PLUGINSDIR\namecompany.ini" "Field 2" "state"
  ReadINIStr $Company "$PLUGINSDIR\namecompany.ini" "Field 4" "state"
  MessageBox MB_OK "$UserName$\r$\n$Company"
  Pop $R0
FunctionEnd

Section ""
  SetOutPath $INSTDIR
  File C:\Windows\system32\notepad.exe
  WriteUninstaller $INSTDIR\uninstall.exe
SectionEnd

Section "Uninstall"
  Delete $INSTDIR\uninstall.exe
  Delete $INSTDIR\notepad.exe
  RMDir $INSTDIR
SectionEnd

Die Erklärungen der Neuerungen:

Page custom

Mit diesem Kommando wird eine Benutzerdefinierte Seite hinzugefügt. Der Parameter getUsername gibt dabei den Namen der Funktion an, die zur Anzeige der Seite aufgerufen werden soll. Die Funktion wird weiter unten erklärt.

Var

Um Variabeln benutzen zu können müssen diese zuerst deklariert werden. Da wir den Benutzernamen und den Firmennamen abfragen werden stellen wir hier zwei Variabeln zur Verfügung, um die eingegebenen Werte abzulegen.

Function ".onInit"

Dies ist eine sogenannte Callback-Funktion. Callback-Funktionen werden an bestimmten Punkten während des Ablaufs des Installers aufgerufen. .onInit wird dabei aufgerufen, wenn der Installer die Initialisierung fast abgeschlossen hat.

Wir benutzen diese Callback-Funktion, um unsere Datei mit der Dialogdefinition in einen temporären Ordner zu entpacken. Dazu wird zuerst mit dem Befehl InitPluginsDir das Verzeichnis $PLUGINSDIR initialisiert. $PLUGINSDIR ist ein temporäres Verzeichnis, dass beim Beenden des Installers wieder gelöscht wird. Als nächstes wird unsere Datei in diesen Ordner kopiert. Somit steht sie während der Installation zur Verfügung.

Function getUsername

Hier nun die schon erwähnte Funktion. Das zentrale Element ist der Aufruf der Funktion „dialog“ aus dem Plug-In InstallOptions. Als Parameter wird die während der Initialisation entpackte Datei angegeben. Da die Funktion „dialog“ einen Rückgabewert auf den Stack speichert müssen wir diesen wieder vom Stack holen. Dazu speichern wir vor dem Aufruf der Funktion „dialog“ den in der Variablen $R0 vorhandenen Wert auf dem Stack. Nach dem ausführen der Funktion „dialog“ holen wir den Rückgabewert vom Stack. Wenn nötig kann der Rückgabewert nun ausgewertet werden. Bevor wir unsere Funktion verlassen stellen wir wieder den vorher auf dem Stack abgespeicherten Wert in die Variable $R0.

Mit ReadINIStr lesen wir die eingegebenen Werte aus den Feldern in die entsprechenden Variablen ein. Diese zeigen wir in unserem Beispiel einfach mit einer MessageBox an, man könnte sie aber auch während der Installation in die Registry schreiben (mit WriteRegStr). Die in die Registry geschriebenen Werte sollten dann aber bei der Deinstallation auch wieder gelöscht werden (mit DeleteRegKey oder DeleteRegValue).

Mehr Auswahl bitte …

Drei Dinge fehlen unserem Installer noch:

  • Auswahl der zu installierenden Komponenten
  • Startmenü-Eintrag
  • Eintrag in der Systemsteuerung zum Entfernen der Software

Mit unserem vierten Installer erfüllen wir auch diese Wünsche. Wie gehabt folgen nach dem Script die Erklärungen der Änderungen.

Name "Forth Installer"
!define INSTALLATIONNAME "MyForthInstaller"
OutFile "fourthinstaller.exe"
InstallDir $PROGRAMFILES\${INSTALLATIONNAME}

Page custom getUsername
Page license
Page components
Page directory
Page instfiles
UninstPage uninstConfirm
UninstPage instfiles

LicenseData "license.txt"

Var UserName
Var Company

Function ".onInit"
  InitPluginsDir
  File /oname=$PLUGINSDIR\namecompany.ini "namecompany.ini"
FunctionEnd

Function getUsername
  Push $R0
  InstallOptions::dialog $PLUGINSDIR\namecompany.ini
  Pop $R0
  ReadINIStr $UserName "$PLUGINSDIR\namecompany.ini" "Field 2" "state"
  ReadINIStr $Company "$PLUGINSDIR\namecompany.ini" "Field 4" "state"
  MessageBox MB_OK "$UserName$\r$\n$Company"
  Pop $R0
FunctionEnd

Section ""
  SetOutPath $INSTDIR
  File C:\Windows\system32\notepad.exe
  WriteUninstaller $INSTDIR\uninstall.exe
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${INSTALLATIONNAME}" "DisplayName" "Forth Installer"
  WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${INSTALLATIONNAME}" "UninstallString" '"$INSTDIR\uninstall.exe"'
  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${INSTALLATIONNAME}" "NoModify" 1
  WriteRegDWORD HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${INSTALLATIONNAME}" "NoRepair" 1

SectionEnd

Section "Sample Text File"
  File "license.txt"
SectionEnd

Section /o "Another Sample Text File"
  File "license2.txt"
SectionEnd

Section "Start Menu Shortcuts"
  CreateDirectory "$SMPROGRAMS\${INSTALLATIONNAME}"
  CreateShortCut "$SMPROGRAMS\${INSTALLATIONNAME}\Uninstall.lnk" "$INSTDIR\uninstall.exe" "" "$INSTDIR\uninstall.exe" 0
  CreateShortCut "$SMPROGRAMS\${INSTALLATIONNAME}\notepad.lnk" "$INSTDIR\notepad.exe" "" "$INSTDIR\notepad.exe" 0
SectionEnd

Section "Uninstall"
  DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${INSTALLATIONNAME}"
  Delete $INSTDIR\uninstall.exe
  Delete $INSTDIR\notepad.exe
  Delete  $INSTDIR\license.txt
  Delete  $INSTDIR\license2.txt
  RMDir $INSTDIR
  Delete "$SMPROGRAMS\${INSTALLATIONNAME}\*.*"
  RMDir "$SMPROGRAMS\${INSTALLATIONNAME}"
SectionEnd

!define

Mit !define definieren wir eine Konstante, die den Namen unserer Installation enthält. Diese Konstante setzten wir dann jedes mal anstelle des Namens ein. Dadurch können wir den Namen einfach an einem Ort ändern und es geht kein Pfad etc. vergessen.

Page component

Durch diesen Eintrag wird die Auswahl der Komponenten angezeigt. Jede Section ist dabei eine Komponente und kann einzeln an- und abgewählt werden. Die Section mit dem leeren Namen wird dabei aber nicht angezeigt, wird aber immer installiert.

Section "Sample Text File"

Eine Section, die einer Komponente entspricht, die an- und abgewählt werden kann. Normalerweise ist eine Komponente automatisch angewählt und wird dementsprechend auch installiert. Falls man optionale Komponenten hat, die im Normalfall nicht installiert werden soll, gibt man diese mit dem Schalter /o (für optional) an.

CreateDirectory

CreateDirectory erzeugt das angegebene Verzeichnis. Falls dabei die in der Hierarchie höher gelegenen Verzeichnisse noch nicht existieren werden diese ebenfalls erstellt.

CreateShortCut

Mit CreateShortcut wird eine Verknüpfung mit dem angegebenen Pfad und Dateiname erstellt.

WriteRegStr, WriteRegDWORD

Um Werte in die Registry zu schreiben benutzt man die Commands WriteRegStr, WriteRegDWORD und ihre verwandten Commands. Falls der Key noch nicht vorhanden ist wird er automatisch erstellt.

DeleteRegKey

DeleteRegKey löscht dementsprechend einen Key aus der Registry.

Ausblick

Nachdem wir nun die Hauptelemente eines Installers behandelt haben betrachten wir im dritten Teil dieses Tutorials das Modern User Interface, um den Installern ein moderneres Erscheinungsbild zu geben.

6 Gedanken zu „NSIS Tutorial Teil 2

  1. brocel1

    Wie kann ich Verknüpfungen erstellen, die für alle Benutzer sichtbar sind?

    aktuell verwende ich dies:

    ; Verknüpfungen
    CreateShortCut „${ProfilePathAllUsers}\DESKTOP\${Installationname}.lnk“ „$INSTDIR\Auswertetool.exe“ „“

    CreateDirectory „$SMPROGRAMS\${INSTALLATIONNAME}“
    CreateShortCut „$SMPROGRAMS\${INSTALLATIONNAME}\Uninstall.lnk“ „$INSTDIR\Uninstall.exe“ „“ „$INSTDIR\Uninstall.exe“ 0
    CreateShortCut „$SMPROGRAMS\${INSTALLATIONNAME}\${Installationname}.lnk“ „$INSTDIR\HelloWorld.exe“ „“ „$INSTDIR\HelloWorld.exe“ 0
    CreateShortCut „$SMPROGRAMS\${INSTALLATIONNAME}\Dokumentation .lnk“ „$INSTDIR\Dokumentation\Dokumentation.pdf“ „“ „$INSTDIR\Dokumentation\Dokumentation.pdf“ 0

    Wenn ich aber einen Adminuser beim installieren angebe, sind für meinen Benutzer keine Verknüpfungen sichtbar.. 🙁

    Antworten
  2. Pingback: NSIS Tutorial in c’t 16/2014 | of bits and bytes

  3. White_Fox

    Ein tolles Tutorial für den Einstieg-Danke. 🙂

    Der thirdinstaller macht in Zeile 13 und 25 allerdings noch Probleme. Und behoben krieg ich sie mit meinem bisherigen Wissen leider nicht. 🙁

    Antworten
    1. Roland Bär Beitragsautor

      Hallo White_Fox

      Schön, dass dir das Tutorial gefällt. Und toll, dass Du den Fehler selber gefunden hast.
      Ich denke, Du hast so schon eine gute Basis um Deinen eigenen Installer erstellen zu können.

      Antworten

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert