Sie sind auf Seite 1von 84

Nullsoft Scriptable Install System

Copyright 2003, Mathias Simmack


Version 1.7.1.090215

Nullsoft Scriptable Install System

ber dieses Dokument


Diese Dokumentation ist keine professionelle Anleitung, die den Anspruch erhebt, wirklich jede
Funktion von NSIS zu erklren. Ich habe mich auf die grundlegenden Funktionen beschrnkt, damit
Sie eine lauffhige Installation erstellen knnen.
Mein Dank fr die Anregung und Untersttzung, sowie fr Kritik und Lob geht an
Christopher Harms
Markus Fuchs

Nullsoft Scriptable Install System

Inhalt
Grundlagen......................................................................................................................................4
Eine Beispielinstallation..................................................................................................................5
Allgemeine Vorbereitungen................................................................................................................6
Grundeinstellungen im Skript.............................................................................................................6
Das Lizenzabkommen.......................................................................................................................7
Dateien hinzufgen............................................................................................................................7
Shell-Erweiterungen...........................................................................................................................9
Spezielle Sektionen.........................................................................................................................10
Untergeordnete Sektionen...............................................................................................................10
Die Uninstall-Sektion........................................................................................................................11
Komponentenauswahl beim Entfernen............................................................................................14
Installationstypen definieren.............................................................................................................15
Verknpfungen................................................................................................................................16
Sprungmarken...............................................................................................................................19
Spracheinstellungen.....................................................................................................................20
Die Sprache fr die moderne GUI ndern........................................................................................21
Das Skript kompilieren..................................................................................................................21
Hinweis zu bzip2 und zur modernen Oberflche..............................................................................22
Die moderne GUI............................................................................................................................22
Das Lizenzabkommen.....................................................................................................................23
Symbole und Bitmaps tauschen.......................................................................................................24
Programme nach der Installation ausfhren....................................................................................24
Nach der Installation Informationen anzeigen..................................................................................25
Einen Link zu einer Webseite anzeigen...........................................................................................25
Die Gruppe im Startmen selbst auswhlen....................................................................................25
Neustart auslsen............................................................................................................................27
Die Beschreibungen von Komponenten anzeigen...........................................................................28
Die Registry....................................................................................................................................29
Dateitypen registrieren.....................................................................................................................29
DWORDs und binre Daten............................................................................................................31
Die Rechtefrage unter Windows NT................................................................................................31
Selbst aufrumen.............................................................................................................................32
INI-Dateien......................................................................................................................................33
Upgrades........................................................................................................................................34
Mehrbenutzer-Umgebungen.........................................................................................................36
Die eingebaute Skriptsprache......................................................................................................37
Das Betriebssystem ermitteln..........................................................................................................38
Sektionen deaktivieren und verschwinden lassen............................................................................38
Bin ich Administrator, oder was?......................................................................................................40
Dialogboxen.....................................................................................................................................41
Die NSIS-Variablen..........................................................................................................................42
Push, Pop und Exch........................................................................................................................43
Strings.............................................................................................................................................44
IntOp und IntCmp............................................................................................................................44
Registryschlssel auflisten...............................................................................................................45
Dateien erzeugen, ergnzen und ihren Inhalt anzeigen...................................................................46
Dateien suchen................................................................................................................................48
Ereignisse des Installers..................................................................................................................50
Headerdateien.................................................................................................................................51
Makros.............................................................................................................................................52

Nullsoft Scriptable Install System

Mehrsprachige Setups..................................................................................................................53
Mehrsprachigkeit bei der modernen Oberflche..............................................................................56
Aufgaben (= Tasks)........................................................................................................................58
Werte an eigene Seiten bergeben.................................................................................................60
Und was ist mit der klassischen GUI und eigenen Seiten?..............................................................61
Seiten im Setup berspringen......................................................................................................62
Kontakt mit dem Microsoft Installer.............................................................................................64
Das Originalprogramm suchen........................................................................................................65
Die Versionsnummer von Programmen ermitteln............................................................................67
Die Alternative - das Produkt bzw. den Patch aufspren.................................................................68
MSI-Setups deinstallieren und blockieren........................................................................................70
Alte NSIS-Anwendungen entfernen..............................................................................................73
Der "Silent Mode".............................................................................................................................75
Idee fr eine Upgradefunktion......................................................................................................75
Patches mit NSIS...........................................................................................................................79
Die Patchdateien erstellen...............................................................................................................80
Die Dateien aktualisieren.................................................................................................................80
Dateien downloaden......................................................................................................................82
Timeout............................................................................................................................................83
Das Interface auf Deutsch...............................................................................................................83

Nullsoft Scriptable Install System

Grundlagen
NSIS ist ein Skriptbasiertes Installationssystem. Im Gegensatz zu Inno Setup fand ich die Syntax
aber anfangs etwas gewhnungsbedrftig. Das mag zwar letztlich Ansichtssache sein, aber ich
muss gestehen, dass ich doch hufiger in die Dokumentation schauen musste, als dies bei Inno
Setup der Fall war.
NSIS gefllt mir aber in Bezug auf die Gre der Setupdateien, weil diese relativ klein sind. Ein
typisches Setup liegt (lsst man die zu installierenden Dateien mal auen vor) im Bereich von 30
bis 50 Kilobytes. Das hngt auch von den Symbolen und Bitmaps ab, die Sie verwenden. Je
aufwndiger und farbintensiver, desto grer wird es natrlich.
Am Beispiel des Programms INI-Cleaner fr LuckieDIPS werde ich Ihnen die wichtigsten Dinge
erklren. In Einzelfllen erlutere ich bestimmte Themen aber auch anhand anderer Anwendungen.
Das liegt dann ganz einfach daran, dass ich diese Themen nicht fr mein Beispielsetup bentige.
Aber vorenthalten wollte ich sie Ihnen auch nicht.

Nullsoft Scriptable Install System

Eine Beispielinstallation
Der INI-Cleaner fr LuckieDIPS besteht aus einer Programmdatei und 5 Dateien, die zum
Quellcode gehren. Das Programm ist zwar nur unter Windows NT und hher lauffhig, allerdings
lsst sich das Setup auf Rckfrage auch unter anderen Windows-Versionen ausfhren.
Ich habe mich dazu entschlossen, damit die Benutzer von 9x-Systemen an die beiden
Installationsskripte herankommen, die im Paket enthalten sind.

Allgemeine Vorbereitungen
Als Setup-Entwickler sollten Sie sich im Vorfeld die Frage stellen, was Sie erreichen wollen. Kurz
gesagt sind folgende Punkte von allgemeiner Wichtigkeit
1. Welche Dateien werden wohin kopiert?
2. Sind Eintrge im Startmen notwendig? Oder in der Registry?
3. Soll der Benutzer die Installation beeinflussen knnen?
usw. usw.

Grundeinstellungen im Skript
Bevor wir mit den Dateien beginnen, mssen wir ein paar Grundeinstellungen vornehmen. Diese
gehren zweckmigerweise an den Anfang des Skriptes, und darum will ich auch mit ihnen beginnen.
Name "INI-Cleaner fr LuckieDIPS"
ComponentText "INI-Cleaner fr LuckieDIPS enthlt \
die folgenden Bestandteile"
DirText "Setup ist bereit zur Installation"
InstallDir $PROGRAMFILES\ICLD
OutFile "icld-ntx86.exe"
Hier sehen Sie gleich eine Besonderheit. Der Backslash \ dient allein stehend als
Zeilenumbruch wenn die Zeile im Skript zu lang ist. Der Compiler akzeptiert dies, und so
habe ich auch keine Schwierigkeiten mit dem Abdrucken von Beispielcode in dieser
Dokumentation. (vgl. dazu Inno Setup)

Name
Name*
ComponentText*
DirText*
InstallDir
OutFile
LicenseData*

Bedeutung
Name des Installers, blicherweise der Name Ihres Produktes.
Wird bei der Auswahl der Komponenten angezeigt.
Wird bei der Verzeichnisauswahl angezeigt.
Voreinstellung des Verzeichnisses.
Name der zu erzeugenden Setupdatei.
Text- oder RTF-Datei, die als Lizenz angezeigt werden soll.

Die mit einem Sternchen versehenen Eintrge sind nur bei der klassischen Oberflche
erforderlich.

Nullsoft Scriptable Install System

Bei der klassischen Oberflche mssen Sie, so widersinnig es auch erscheinen mag, "DirText"
und "ComponentText" benutzen! Widersinnig, weil man normalerweise auf die Idee kommt,
diesen Attributen Standardtexte wie
Whlen Sie ein Verzeichnis aus
Whlen Sie die Komponenten aus,
zuzuordnen. Das Problem ist, dass NSIS genau diese Standardtexte bereits von sich aus anzeigt.
Es wre also doppelt gemoppelt, wenn Sie das auch noch einmal schreiben. Und wenn Sie die
beiden Attribute weglassen, dann sehen Sie weder eine Komponenten- noch eine
Verzeichnisauswahl. Stattdessen installiert NSIS ohne weitere Rckfragen Ihr Programm, was wohl
kaum in Ihrem Sinn sein drfte. Gar nicht zu reden davon, dass der Anwender davon sicher auch
nicht begeistert ist.
Aus dem Grund habe ich mich fr die oben gezeigten Texte entschieden, weil die halbwegs zur
Situation passen

Das Lizenzabkommen
Eine kleine Anmerkung zu dieser Seite sei mir gestattet. Wenn Sie sie benutzen, wird
standardmig ein Fenster mit dem Lizenztext gezeigt, und wenn Sie auf den Button "Annehmen"
klicken, wird die Installation fortgesetzt.
Daneben haben Sie aber auch die Mglichkeit, eine Checkbox oder Radiobuttons zu verwenden
und das Setup damit an andere typische Vertreter anzugleichen. Um die Annahme der Lizenz also
zum Beispiel explizit mit einer Checkbox besttigen zu lassen, definieren Sie
LicenseForceSelection "checkbox" "Ja, ich will"
Der rot markierte Text ist optional und muss nicht angegeben werden.
Die Alternative wren zwei Radiobuttons, von denen nur einer ausgewhlt werden kann. Der erste
dient dazu, der Lizenz zuzustimmen, mit dem zweiten lehnen Sie die Lizenz ab. Hier haben Sie die
Mglichkeit, zwei Texte anzugeben - logischerweise den zustimmenden und ablehnenden Text.
LicenseForceSelection "radiobuttons" "Ja, ich will" "Nee"
Wenn Sie diese Texte (in beiden Fllen) weglassen, benutzt der Installer Standardtexte.

Nullsoft Scriptable Install System

Dateien hinzufgen
Fr Dateien bentigen wir so genannte Sections. Es hnelt meiner Meinung nach Delphi oder VB
ein bisschen, denn die Syntax sieht wie folgt aus
Section "Bezeichnung"
...
SectionEnd
Dazwischen spielt sich nun alles ab. Hier muss ich ein wenig vorgreifen und auf die Auswahl der
Komponenten eingehen, wie auch bereits auf dem Bild auf der letzten Seite zu erkennen ist.
Wenn Sie Ihre Dateien einfach nur ohne Auswahl installieren lassen wollen, dann definieren Sie
eine Sektion, deren Bezeichnung vollkommen egal ist (lassen Sie sie leer!), und entfernen Sie aus
dem Skript "ComponentText". Wie ich bereits schrieb, wird die Komponentenauswahl gar nicht
erst angezeigt, wenn dieses Attribut fehlt.
Wir mchten dem Anwender allerdings die Auswahl gestatten, und darum mssen wir
entsprechende Sektionen fr jede Komponente erstellen. Und die Bezeichnungen, die Sie hier
benutzen, werden spter in der Komponentenauswahl angezeigt. Unsere erste Komponente ist nur
die Programmdatei. Die Sektion dazu sieht deshalb so aus
Section "INI-Cleaner fr LuckieDIPS"
SectionIn RO
SetOutPath $INSTDIR
File "..\cleanup.exe"
SectionEnd
Name
SectionIn
SetOutPath
File

Bedeutung
Flags bezglich Installationstypen. (RO = read only, Sektion kann
nicht abgewhlt werden)
Setzt das Zielverzeichnis (ggf. wird dieses auch erzeugt).
Name der in das gewhlte Verzeichnis zu kopierenden Datei.

Diesmal mchte ich nicht vorgreifen, darum gehe ich auf die Desktop-Verknpfung des Programms
erst spter ein. Stattdessen machen wir ein kleines Experiment mit der Quellcode-Komponente.
Normalerweise werden die Quellcodedateien unseres Beispiels im selben Ordner wie das
Programm abgelegt. In dem Fall gbe es aber nichts mehr dazu zu sagen, denn die Syntax ist
exakt die selbe wie im oben gezeigten Beispiel.
Sie knnen die Dateien nun aber sortieren lassen und in einem Unterverzeichnis namens "source"
entpacken lassen. Dazu hngen Sie den gewnschten Pfad einfach an die Variable "$INSTDIR"
an. NSIS erzeugt dann automatisch den Ordner
Section "Quellcode"
SetOutPath $INSTDIR\source
File "..\cleanup.dpr"
...
SectionEnd
Wie Sie sehen ist die Methode recht einfach. Und eine separate Anweisung zum Erzeugen der
Unterverzeichnisse ist ebenfalls nicht notwendig.
Sie knnen den Namen einer Datei auch beim Entpacken ndern. Dazu benutzen Sie den
Parameter "/oname" und hngen den gewnschten neuen Namen an, beispielsweise
File /oname=$INSTDIR\NeuerName.Ext "AlterName.Ext"

Nullsoft Scriptable Install System

In dem Fall wrde der Compiler die Datei "AlterName.Ext" suchen und in das Setup aufnehmen,
bei der Installation wrde sie aber den Namen "NeuerName.Ext" bekommen.
Ebenfalls interessant ist, dass Sie den Zielpfad innerhalb einer Sektion auch ndern knnen. So
knnen Sie einen Teil der Dateien in ein anderes Verzeichnis kopieren lassen als den Rest. Um
etwa das Installationsskript in den Ordner "setup" zu kopieren, schreiben Sie
Section "Quellcode"
; hier werden die anderen Dateien installiert
; ...
SetOutPath $INSTDIR\setup
File "icld.nsi"
SectionEnd
Sie knnen auch rekursiv ganze Ordner angeben. Das ist ntzlich, wenn Sie sehr viele Dateien in
Ihr Skript aufnehmen mssen. Dazu hngen Sie einfach den Parameter "/r" an den Befehl,
beispielsweise
SetOutPath $INSTDIR\Samples
File /r "..\Samples\*"
Allerdings werden auf die gezeigte Weise wirklich alle Dateien kopiert. Wenn Sie das verhindern
wollen, dann sollten Sie mit Hilfe von Wildcards die zu bercksichtigenden Dateitypen etwas
eingrenzen.
berschreibmodus
Die Installation der Dateien kann von bestimmten Bedingungen abhngig gemacht werden. Im
Normalfall werden alle Dateien entpackt, ob das nun sinnvoll und notwendig ist oder nicht. Dafr
verantwortlich ist der Befehl "SetOverwrite", dessen Standardwert "on" ist
Name
on
off
try
ifnewer
ifdiff

Bedeutung
Alle Dateien werden entpackt und vorhandene ggf. berschrieben.
Bereits vorhandene Dateien werden nicht berschrieben.
Es wird versucht, Dateien zu berschreiben. Ist das nicht mglich, wird die Datei
ignoriert und nicht entpackt.
Die Datei wird nur berschrieben, wenn sie neuer ist. Zur Prfung werden
allerdings nur Datum und Uhrzeit herangezogen. Eine tatschliche Prfung, ob die
Datei aktueller ist, findet nicht statt.
Die Datei wird berschrieben, wenn sie unterschiedlich (lter oder neuer) ist.
Dadurch besteht die Gefahr, eine neue Datei durch eine ltere zu ersetzen.

Sie knnen diesen Befehl innerhalb einer Sektion mehrfach wechseln.

Nullsoft Scriptable Install System

Shell-Erweiterungen
Wenn Sie eine Shell-Erweiterung, typischerweise eine DLL, installieren mssen, dann gehen Sie
zunchst wie bereits beschrieben vor. Wenn die Bibliothek in das Zielverzeichnis installiert wurde,
knnen Sie die Shell-Erweiterung mit dem Befehl "RegDll" im System registrieren
RegDll "$INSTDIR\ShellErweiterung.dll"
blicherweise heit die Funktion, die dabei aufgerufen wird, "DllRegisterServer". Wenn das bei
Ihrer Shell-Erweiterung nicht der Fall ist, knnen Sie zustzlich den Namen der Funktion angeben
RegDll "$INSTDIR\ShellErweiterung.dll" "ShellFunktion"
Das Gegenstck dieses Befehls lautet "UnRegDll". Ohne zu weit vorgreifen zu wollen: diesen
Befehl bentigen Sie zum Entfernen der Shell-Erweiterung. Sie drfen nicht vergessen, dass die
Bibliothek im System registriert ist. Wenn Sie die Datei bei der Deinstallation einfach lschen, wird
dadurch nicht zwangslufig auch die Registrierung aufgehoben.
Als einzigen Parameter knnen Sie hier nur den Namen der Bibliothek angeben.

Spezielle Sektionen
Vielleicht stehen Sie einmal vor dem Problem, dass Sie bestimmte Dateien generell kopieren
mssen oder wollen, ohne dass der Anwender die Wahl hat. Dahinter muss ja keine bse Absicht
stecken. Das kann etwa bei so genannten "gemeinsam genutzten Dateien" der Fall sein.
Natrlich knnten Sie eine nicht vernderbare Sektion definieren, die der Anwender nicht abwhlen
kann. Noch besser wre es aber, er wrde sie erst gar nicht sehen. Um das zu erreichen, gengt
es, den Namen der Sektion leer zu lassen oder mit einem Minus zu beginnen, also
Section ""
oder
Section "-Bezeichner"
Wenn Sie dem Namen der Sektion ein Ausrufungszeichen voranstellen, wird diese im Installer fett
markiert. Das bietet sich speziell bei Sektionen an, die installiert werden mssen, bzw. die
irgendwie von besonderer Bedeutung sind
Section "!Bezeichner"
Wenn die Sektion standardmig nicht gewhlt sein soll, dann benutzen Sie den Parameter "/o"
Section /o "abgewhlte Sektion"
SectionEnd

10

Nullsoft Scriptable Install System

Untergeordnete Sektionen
Wenn Sie den Microsoft Installer kennen, dann wissen Sie vielleicht, dass man dort die so
genannten Features auch unterordnen kann. Das bedeutet, es gibt einen Haupteintrag, der
seinerseits einen oder mehrere Untereintrge besitzt. Man kann nun alle Eintrge aus- oder
abwhlen, indem man den Haupteintrag benutzt. Oder man hat die Mglichkeit, einzelne
Untereintrge aus- bzw. abzuwhlen.
NSIS bietet mit der Direktive "SectionGroup" etwas Vergleichbares. Als Beispiel habe ich die
Quellcode-Komponente aufgetrennt, so dass Sie nun zwischen der Installation von Quellcode und
Setup-Skripten whlen knnen.
SectionGroup "Quellcode"
Section "${NAME}"
SectionIn 1
SetOutPath $INSTDIR
File "..\cleanup.dpr"
File "..\dialog.rc"
File "..\dialog.res"
File "..\make.bat"
File "..\SysUtils.inc"
SectionEnd
Section "Setup-Skripte"
SectionIn 1
SetOutPath \
$INSTDIR\setup
File "icld.nsi"
File "icld.classic.nsi"
File "icld.iss"
SectionEnd
SectionGroupEnd
Wenn Sie eine solche Sektion gleich aufgeklappt anzeigen wollen, dann benutzen Sie den
Parameter "/e" vor dem Sektionsnamen
SectionGroup /e "Quellcode"
Achtung! Die Angaben "SubSection" und "SubSectionEnd" sind seit Version 2.05
veraltet, werden aber weiterhin untersttzt.

11

Nullsoft Scriptable Install System

Die Uninstall-Sektion
Ein scheinbarer Nachteil von NSIS ist, dass standardmig kein Deinstaller erzeugt wird. In dem
Fall mssten die kopierten Dateien usw. manuell entfernt werden, was dem Anwender
selbstverstndlich nicht zuzumuten ist.
Auf der anderen Seite bietet sich dieses Verhalten fr Updates oder Patches an, bei denen Sie vorhandene Dateien berschreiben wollen. In so einem Fall wre ein Deinstaller unntig. Es ist also
eine Frage der Betrachtungsweise.
Wir wollen jedoch eine Deinstallationsfunktion anbieten. Das funktioniert, nur mssen wir uns eben
selbst um alle erforderlichen Schritte kmmern. Zweckmig ist hier eine nicht sichtbare Sektion im
Skript, die unabhngig von den Benutzerangaben immer ausgefhrt wird. In dieser Sektion legen
wir auch die beiden notwendigen Registryeintrge an, damit unser Programm in der
Systemsteuerung erscheint
Section "-MakeDeinstaller"
WriteUninstaller "$INSTDIR\uninstal.exe"
IfFileExists "$INSTDIR\uninstal.exe" 0 NoRegLink
WriteRegStr HKLM "${UNINSTREGKEY}" \
"DisplayName" "${NAME} ${VERSION}"
WriteRegStr HKLM "${UNINSTREGKEY}" \
"UninstallString" "$INSTDIR\uninstal.exe"
NoRegLink:
SectionEnd
Ich habe die Sektion mit einem Minus gekennzeichnet, wodurch sie in der benutzerdefinierten Auswahl nicht erscheint.
Die Anweisung "WriteUninstaller" erzeugt im Ordner der Anwendung das entsprechende Programm, mit dem sie sich deinstallieren lsst. Als Parameter geben Sie lediglich den gewnschten
Namen an, den Sie frei whlen knnen.
Abhngig davon ("IfFileExists") werden die beiden schon erwhnten Registryeintrge
angelegt, die das unter Windows bliche System bercksichtigen. Das bedeutet, deinstallierbare
Software wird blicherweise im Schlssel
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
aufgelistet. Damit das Programm auch in der Systemsteuerung erscheint, muss dazu allerdings ein
weiterer Schlssel erzeugt werden, der blicherweise dem Namen der installierten Anwendung
entspricht. Das kann auch eine Kurzform sein. Nur eindeutig sollte sie sein, damit nicht
versehentlich die Deinstallationsdaten einer anderen Anwendung berschrieben werden.
Notwendig sind dann speziell zwei Eintrge, die es immer geben muss, damit a) unsere
Anwendung fr den Benutzer sichtbar ist, und b) durch ihn entfernt werden kann
Name
DisplayName
UninstallString

Bedeutung
Erscheint als Beschreibung in der Systemsteuerung
Pfad zum Deinstallationsprogramm

Alternativ dazu knnen Sie Ihre Software auch entfernbar machen, aber beispielsweise nicht durch
den Benutzer sondern durch ein anderes Programm. Wenn Ihre Anwendung etwa aus mehreren
Modulen besteht, von denen aber nur das Hauptmodul sichtbar sein soll oder darf. Der Internet
Explorer von Microsoft nutzt diese Technik, um ein paar seiner Komponenten vor Ihnen zu verstecken.

12

Nullsoft Scriptable Install System

Benutzen Sie in diesem Fall den Prfix "Quiet" vor den in der Tabelle gezeigten Eintrgen. Ihre
Anwendung ist dann in der Systemsteuerung nicht zu sehen, lsst sich aber dennoch entfernen wenn Sie den entsprechenden Wert auslesen
IfFileExists "$INSTDIR\uninstal.exe" 0 NoRegLink
WriteRegStr HKLM "${UNINSTREGKEY}" \
"QuietDisplayName" "${NAME} ${VERSION} (Heimlich)"
WriteRegStr HKLM "${UNINSTREGKEY}" \
"QuietUninstallString" "$INSTDIR\uninstal.exe"
Als dritte Mglichkeit knnen Sie Ihr Produkt auch einem anderen unterordnen. Allerdings ist das
erst ab Windows XP SP 2 mglich. Hier gibt es zwei neue Stringwerte namens "ParentKeyName"
und "ParentDisplayName". Den ersten werden Sie grundstzlich brauchen, weil er auf den
Schlssel des gewnschten bergeordneten Programms verweist.
Nehmen wir als Beispiel an, Sie wollen Ihr Produkt dem Acrobat Reader 5 unterordnen. Der benutzt
im Uninstall-Zweig Registry den Schlsselnamen "Adobe Acrobat 5.0". Und genau diesen
Namen geben Sie als "ParentKeyName" fr Ihr Produkt an
WriteRegStr HKLM "${UNINSTREGKEY}" \
"ParentKeyName" "Adobe Acrobat 5.0"
Und damit erscheint unser Programm als Update des Readers. Es ist aber nur sichtbar, wenn die
Checkbox oben rechts ausgewhlt ist.

Das System wird natrlich eigentlich von Microsoft verwendet, um eingespielte Updates des
Systems logisch zu gliedern. Der Vorteil ist, dass die Systemsteuerung auch endlich aufgerumt ist.
Hatte man frher Hotfixes usw. installiert, quoll die Anzeige buchstblich ber.
Der zweite String, "ParentDisplayName", ist nur wichtig, wenn der bergeordnete Schssel nicht
existiert. Und genau das System verwendet Microsoft ja fr die Systemupdates. Im Normalfall sind
diese nmlich nicht zu sehen.
Um das gleiche bei unserem Beispiel zu erreichen, ndern wir zunchst den "ParentKeyName",
damit es sich nun um einen nicht existierenden Schlssel handelt. Und wir weisen dem zweiten
String "ParentDisplayName" einen erklrenden Text zu, quasi eine Rubrik, unter der unser
Programm dann erscheinen soll, bspw.
WriteRegStr HKLM "${UNINSTREGKEY}" \
"ParentKeyName" "PersonalCleanUpTools"
WriteRegStr HKLM "${UNINSTREGKEY}" \
"ParentDisplayName" "System-Suberungstools"
und voil, da ist unsere neue Rubrik inkl. unseres Programms

13

Nullsoft Scriptable Install System

Es fehlt jetzt nur noch die eigentliche "Uninstall"-Sektion, in der wir aufrumen. Der Name
dieser Sektion ist fest vorgeschrieben und darf von Ihnen nicht anderweitig benutzt werden. Was
Sie hier angeben, wird dem Deinstallationsprogramm zugeordnet.
Was mssen wir tun?
Zum einen mssen wir die Dateien und Ordner unserer Anwendung lschen. Falls vorhanden muss
auch die Desktop-Verknpfung entfernt werden. Und nicht zu vergessen die beiden
Registryeintrge, damit die Anwendung wieder aus der Systemsteuerung verschwindet
Section Uninstall
DeleteRegKey HKLM "${UNINSTREGKEY}"
IfFileExists "$DESKTOP\${NAME}.lnk" 0 NoLink
Delete "$DESKTOP\${NAME}.lnk"
NoLink:
Delete "$INSTDIR\uninstal.exe"
Delete "$INSTDIR\*"
RMDir /r "$INSTDIR"
SectionEnd
Sie sehen, dass ich im Skript Symbole benutzt habe, "${UNINSTREGKEY}"
beispielsweise. Dabei handelt es sich nicht um NSIS-Variablen, sondern das sind
Deklarationen, die ich am Anfang des Skriptes eingefgt habe.
Das ist meiner Meinung nach sehr ntzlich, da speziell Namen und Versionsnummer
doch hufiger gebraucht werden. ndert sich etwa die Versionsnummer, mssten Sie
normalerweise das Skript durchsuchen und entsprechend anpassen. Wenn Sie
stattdessen eine Deklaration verwenden, dann ndern Sie nur diese, und es wirkt sich
auf das gesamte Skript aus. Allerdings handelt es sich dabei um Konstanten, die Sie
einmal festlegen und deren Wert Sie danach nicht mehr ndern knnen.
Folgendes finden Sie daher am Anfang des Beispielskriptes
!define NAME "INI-Cleaner fr LuckieDIPS"
!define VERSION "0.3"
!define UNINSTREGKEY \
"Software\Microsoft\Windows\CurrentVersion\Uninstall\ICLD"
An dieser Stelle kann ich auf etwas eingehen, das ich bereits benutzt habe Die Funktion "IfFileExists" prft, ob der Desktop-Link vorhanden ist und entfernt ihn ggf. Als
ersten Wert geben Sie die Sprungmarke fr eine positive Prfung an. Der zweite Wert bezeichnet
die Sprungmarke fr den Fall, dass die Datei nicht gefunden wurde
IfFileExists "$DESKTOP\${NAME}.lnk" 0 NoLink
Wenn der Vergleich negativ ausfllt, dann wird die rot markierte Sprungmarke ausgefhrt. In dem
Fall gibt es den Shortcut nicht, und Sie knnen das Lschen bergehen. Im Prinzip nicht wirklich
schwer, wenn man ein wenig Erfahrung mit irgendeiner Programmiersprache hat.
Auch die benutzten Lschanweisungen erklren sich eigentlich von selbst. Der Vollstndigkeit
halber mchte ich sie aber kurz auflisten
Name
DeleteRegKey
Delete
RMDir
14

Bedeutung
Entfernt den Registryeintrag aus der Systemsteuerung
Lscht einzelne oder mehrere Dateien (Wildcards sind mglich)
Lscht Verzeichnisse - mit "/r" auch rekursiv

Nullsoft Scriptable Install System

Komponentenauswahl beim Entfernen


In der aktuellen Version kann auch der Deinstaller mit einer Komponentenauswahl ausgestattet
werden. hnlich wie bei der Installation knnen Sie so auch beim Deinstallieren die Komponenten
auswhlen, die entfernt werden sollen.
Dazu erstellen Sie einfach Sektionen, die mit dem Prfix "un." beginnen, etwa
Section "un.INI-Cleaner fr LuckieDIPS"
...
SectionEnd
Anstelle einer kompletten Deinstallation knnen Sie auf diese Weise genau festlegen, wann welche
Dateien und/oder sonstige Eintrge entfernt werden sollen. Die Benutzung der "Uninstall"Sektion ist damit nicht zwangslufig erforderlich.
Allerdings sollten Sie auch an den Uninstaller denken, der auf diese Weise ja nur die ausgewhlten
Komponenten entfernt, selbst aber zurckbleibt. Zweckmig wre daher eine spezielle Sektion,
die fr das Entfernen von allen Komponenten verantwortlich ist.
In dem Fall sollten Sie diese Sektion vor dem Anzeigen der Auswahl allerdings abwhlen. Und
wenn sich der Anwender fr die vollstndige Deinstallation entscheidet, wre es zweckmig, die
brigen Sektionen auf Read only zu setzen.
Ich habe es allerdings so gemacht, dass die Sektion fr die vollstndige Deinstallation die
komplette Logik zum Entfernen von allen Komponenten enthlt. Es wre in dem Fall also
unerheblich, ob der Anwender die anderen Komponenten ab- oder auswhlen kann - sobald er die
vollstndige Deinstallation whlt, wird auch alles entfernt. J
Damit Sie die Komponentenauswahl auch sehen, mssen Sie die Seiten des Setup selbst
definieren. Andernfalls wird das Programm wie bisher ohne weitere Rckfrage deinstalliert.
Allerdings mssen Sie alle Seiten angeben, die Sie sehen wollen, da der Compiler ansonsten eine
Warnung ausgibt. Eine typische Anweisung wre
Page components
Page directory
Page instfiles
UninstPage components
UninstPage instfiles
Im Skript "icld.classic.un.nsi", das dem INI-Cleaner fr LuckieDIPS beiliegt,
finden Sie eine Demonstration dieser Technik.

15

Nullsoft Scriptable Install System

Installationstypen definieren
Von Inno Setup kennen Sie vielleicht die Auswahlbox mit Installationstypen wie "Vollstndig",
"Minimal" usw. Das lsst sich auch bei NSIS realisieren. Dazu definieren Sie die gewnschten
Installationstypen am besten vor den Sektionen
InstType "Vollstndig"
InstType "Kompakt"
Der Installationstyp "Benutzerdefiniert" wird automatisch ergnzt. Maximal sind 32
verschiedene Typen mglich.

Jeder der definierten Typen besitzt eine Indexnummer, die bei Eins beginnt und sich nach der
Reihenfolge ihrer Deklaration im Skript richtet. So htte in obigem Beispiel die "Vollstndige"
Installation die Nummer Eins, die "Kompakte" die Nummer Zwei, usw.
Die Zuordnung zwischen diesen Typen und den Sektionen findet nun mit Hilfe dieser
Indexnummern statt. Das Attribut "SectionIn" kennen Sie bereits, weil wir damit die erste Sektion
nur lesbar gemacht haben. Der Benutzer kann diese Sektion also nicht verndern.
An der gleichen Stelle geben Sie die Indexnummern der Installationstypen ein, die in der Sektion
gltig sein sollen. Das Programm, das ja zur ersten Komponente gehrt, soll immer installiert
werden, also geben Sie die Nummern beider Typen an
Section "INI-Cleaner fr LuckieDIPS"
SectionIn 1 2 RO
...
Dagegen sollen die Quellcodes nur bei der vollstndigen Installation als ausgewhlt markiert
werden. Hier geben Sie demzufolge nur die eine Nummer des entsprechenden Installationstyps an
Section "Quellcode"
SectionIn 1
...
Die Auswahl der einzelnen Komponenten ndert sich damit abhngig von dem Typ, den der
Anwender whlt. Und auf der anderen Seite springt der Installationstyp von selbst auf "benutzerdefiniert", sobald der Anwender bestimmte Komponenten abwhlt.

16

Nullsoft Scriptable Install System

Verknpfungen
Als nchstes wollen wir eine Verknpfung fr das Programm erzeugen. Das Prinzip bleibt das
gleiche: Verknpfungen u.a. werden auch in eben gezeigten Sektionen definiert.
Sie knnen die Verknpfungen selbstverstndlich direkt in den Sektionen unterbringen, in denen
die dazu gehrenden Dateien kopiert werden. Durch das Auslagern in eigene Sektionen berlassen
Sie allerdings dem Anwender spter die Wahl. Er kann entscheiden, ob er die Verknpfung will
oder nicht.
Eintrge im Startmen werden vom Anwender in den meisten Fllen erwartet. Diese Verknpfungen knnen Sie also in den Sektionen unterbringen, in denen die Dateien kopiert
werden. Spezielle Shortcuts, wie solche auf dem Desktop, sollten Sie aber in eine eigene
Sektion eintragen.
Wie wird die Verknpfung nun angelegt? NSIS kennt den Befehl "CreateShortCut", der als
ersten Parameter den Namen der Verknpfung erwartet. Verknpfungen sind, wie Sie sicher
wissen, LNK-Dateien, darum mssen Sie systembedingte Einschrnkungen in Kauf nehmen.
Bestimmte Zeichen sind nicht erlaubt, und mehrere Dateien mit identischen Namen sollte es besser
nicht geben.
Der zweite Parameter ist dann der Verweis auf die zu linkende Datei
Section "Desktop-Verknpfung"
SectionIn 1 2
IfFileExists "$INSTDIR\cleanup.exe" 0 NoLink
CreateShortCut "$DESKTOP\${NAME}.lnk" "$INSTDIR\cleanup.exe"
NoLink:
SectionEnd
Selbstverstndlich sind auch die anderen typischen Parameter mglich. Etwa eine Symboldatei
oder ein Kommentar. Die Parameter mssen allerdings in der folgenden Reihenfolge durch
Leerzeichen getrennt angehangen werden
Name
Parameters
Icondatei
Icon-Index
Startoptionen
Shortcut
Description

Bedeutung
Evtl. Kommandozeilenparameter fr das Programm
Name der Symboldatei, die verwendet werden soll
Index des anzuzeigenden Symbols (null-basierend)
Minimiert, maximiert, und hnliche Flags
Hotkey
Beschreibung fr Windows ME, 2000 und hher

Fr eine Verknpfung, die eine externe Symboldatei benutzt, gengt beispielsweise die folgende
Anweisung
CreateShortCut "$DESKTOP\${NAME}.lnk" \
"$INSTDIR\cleanup.exe" "" "$INSTDIR\jim.ico" 0
Die rot markierte Null bezeichnet dabei den Index des Symbols in der angegebenen Datei.
Notwendig ist sie aber nur, wenn Sie eine Datei bergeben, die mehr als ein Symbol enthlt. Im
obigen Beispiel knnen Sie sie ebenso gut auch weglassen.

17

Nullsoft Scriptable Install System

Die Startoptionen (sprich: die Art, wie das Fenster der Anwendung erscheint) richten sich nach den
fr Windows gltigen Werten. Wenn Sie selbst programmieren, dann werden Sie Werte wie
SW_SHOW sicher kennen. Soll das Programm beispielsweise minimiert starten, dann lautet die
Anweisung dafr
CreateShortCut "$DESKTOP\${NAME}.lnk" \
"$INSTDIR\cleanup.exe" "" "" 0 SW_SHOWMINIMIZED
usw. Die untersttzten Werte finden Sie in der NSIS-Dokumentation.
Verknpfungen im Startmen
Als letztes Beispiel soll noch eine Verknpfung im Startmen angelegt werden. Hier bentigen wir
die Variable "$SMPROGRAMS", die den "Programme"-Ordner im Startmen reprsentiert. Dazu
mssen wir aber erst einen eigenen Ordner anlegen, den wir fr unsere Anwendung verwenden
knnen. Der Befehl dafr lautet "CreateDirectory" und erwartet als Parameter den
gewnschten Namen
CreateDirectory "$SMPROGRAMS\${NAME}"
Wenn Sie den Ordner nicht erstellen, kann die Verknpfung nicht angelegt werden
CreateShortCut "$SMPROGRAMS\${NAME}\Setup.lnk" \
"$INSTDIR\setup"
Als Ergnzung mchte ich ein paar der wichtigsten Variablen von NSIS auflisten
Name
$PROGRAMFILES
$DESKTOP
$EXEDIR
$WINDIR
$SYSDIR
$TEMP
$STARTMENU
$SMPROGRAMS
$SMSTARTUP
$QUICKLAUNCH

Bedeutung
Der "Programme"-Ordner auf der Festplatte
Der Desktop-Ordner
Pfad der Setupdatei
Das Windows-Verzeichnis
Das System-Verzeichnis
Das Temp-Verzeichnis
Das Startmen
Startmen/Programme
Der Autostart-Ordner im Startmen
Der Schnellstart-Ordner

Hinweis zum Arbeitsverzeichnis


Wenn die Verknpfung ein bestimmtes Arbeitsverzeichnis voraussetzt, dann mssen Sie dieses
Verzeichnis vorher einstellen. Nehmen wir als Beispiel an, Sie wollen Ihre Anwendung starten, die
dann ihre Dateien in einem Unterordner namens "data" ablegen soll. In dem Fall legen Sie also
zuerst das Zielverzeichnis fest
SetOutPath "$INSTDIR\data"
und dann erstellen Sie die Verknpfung wie bereits beschrieben
CreateShortCut "$DESKTOP\${NAME}.lnk" "$INSTDIR\cleanup.exe"
Das zuvor gesetzte Verzeichnis wird dann
automatisch im Feld "Ausfhren in ..."
eingetragen.

18

Nullsoft Scriptable Install System

Verzeichnisverknpfungen
Diese speziellen Verknpfungen sind erst ab Windows 2000 mglich und zeigen den Inhalt des
Ordners selbst an. Alle Dateien und Ordner werden wie Meneintrge behandelt. Bei einer
normalen Verknpfung dagegen wrde sich ein separates Fenster mit dem Inhalt ffnen.
Fr diese Art der Verknpfung ist allerdings etwas Vorarbeit erforderlich. Zuerst mssen Sie einen
leeren Ordner im Startmen erstellen, der sozusagen als Container verwendet wird
CreateDirectory "$SMPROGRAMS\$SMFolder\$(SourceCode)"
In dem Ordner erstellen Sie eine versteckte Systemdatei namens "desktop.ini", die folgenden
Inhalt haben muss
WriteIniStr "$SMPROGRAMS\$SMFolder\$(SourceCode)\desktop.ini" \
".ShellClassInfo" "CLSID2" "{0AFACED1-E828-11D1-9187-B532F1E9575D}"
WriteIniStr "$SMPROGRAMS\$SMFolder\$(SourceCode)\desktop.ini" \
".ShellClassInfo" "Flags" "2"
SetFileAttributes "$SMPROGRAMS\$SMFolder\$(SourceCode)\desktop.ini" \
FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM
Dann erzeugen Sie noch die eigentliche Verknpfung, die den Namen "target.lnk" tragen muss.
Und zu guter Letzt aktivieren Sie den Schreibschutz fr den Ordner
CreateShortcut "$SMPROGRAMS\$SMFolder\$(SourceCode)\target.lnk" \
"$INSTDIR\source"
SetFileAttributes "$SMPROGRAMS\$SMFolder\$(SourceCode)" \
FILE_ATTRIBUTE_READONLY
Und voil

19

Nullsoft Scriptable Install System

Sprungmarken
Erwhnt und gezeigt habe ich die Sprungmarken ja bereits. Noch einmal das Beispiel, abhngig
vom Ergebnis von "IfFileExists"
IfFileExists "$DESKTOP\${NAME}.lnk" Found_Jump NoLink
Found_Jump:
...
NoLink:
In den meisten Fllen geben Sie als erste Sprungmarke immer die an, die ausgefhrt werden soll,
wenn eine Bedingung zutrifft. Optional knnen Sie eine zweite Sprungmarke angeben, die
ausgefhrt wird, wenn die Bedingung nicht zutrifft. Normalerweise ist das aber nicht erforderlich,
denn Sie knnen das Skript auch einfach weiterlaufen lassen.
Daneben gibt es noch relative Sprnge zum bergehen von Skriptzeilen, ohne dass Sie dafr
Sprungmarken definieren mssen. Das Prinzip habe ich bei der "Uninstall"-Sektion verwendet.
So wird zuerst geprft, ob die Desktop-Verknpfung vorhanden ist
IfFileExists "$DESKTOP\${NAME}.lnk" 0 +2
Delete "$DESKTOP\${NAME}.lnk"
Besser gesagt: eigentlich wird geprft, ob sie nicht vorhanden ist. Wenn die Bedingung zutrifft,
dann wird die Anweisung +2 wirksam. Damit wird die Lschanweisung bersprungen und mit der
Anweisung in der bernchsten Zeile weitergemacht.
Beachten Sie, dass Sie bei relativen Sprngen eine Zeile mehr angeben. Das liegt daran, dass die
Zeile, in der die Sprunganweisung (+2, beispielsweise) steht, auch gezhlt wird. Quasi ein "von hier
aus". Als Beispiel
StrCpy $0 "123"
StrCmp $0 "123" +1
MessageBox MB_OK "Wenn Sie das sehen, sind Sie zu kurz gesprungen."
MessageBox MB_OK "Das hier sollten Sie nmlich sehen!"
+2 wre Fall richtig, wenn Sie die erste Dialogbox berspringen wollen. Mit den Leerzeilen im Skript
hat das brigens nichts zu tun! Die werden vom Compiler ignoriert.
Sprnge kann man auch innerhalb des Skriptes mit "goto" machen. Sie knnen entweder ein
Sprungziel definieren, oder mit + und einem numerischen Wert die entsprechenden Zeilen
berspringen
goto Ziel
MessageBox MB_OK "Nie zu sehen"
goto +2
MessageBox MB_OK "Auch nicht zu sehen"
Ziel:

20

Nullsoft Scriptable Install System

Spracheinstellungen
Die Standardsprache von NSIS ist Englisch. Wie bereits im Vorwort erwhnt habe ich in Version
1.9x keine Mglichkeit zum ndern der Sprache gefunden. Darum bin ich auch zur Version 2.0
gewechselt, in der das mglich ist, und die auch diverse Sprachdateien mitbringt.
Um die Sprache auf Deutsch umzustellen, fgen Sie bitte die folgende Anweisung am Anfang des
Skriptes ein
LoadLanguageFile "${NSISDIR}\Contrib\Language files\German.nlf"

Die Sprache fr die moderne GUI ndern


Wenn Sie die moderne, Assistenten-hnliche Oberflche verwenden mchten, dann geben Sie die
gewnschte Sprache nicht mit dem obigen Befehl sondern mit der Anweisung "!insertmacro" an
!insertmacro MUI_LANGUAGE "German"

21

Nullsoft Scriptable Install System

Das Skript kompilieren


Wenn Sie das Setup zu Testzwecken erzeugen mchten, dann speichern Sie die Skriptdatei und
klicken Sie sie mit der rechten Maustaste an. Wenn NSIS installiert ist, sollten Sie im Kontextmen
der Datei zwei Punkte finden, die "Compile NSIS Script" heien.
Der Unterschied zwischen beiden Menpunkten ist die Art der verwendeten Komprimierung. Mit
dem ersten Eintrag verwendet NSIS entweder die Standardmethode (zlib) bzw. die, die Sie im
Skript eingetragen haben. Dazu schreiben Sie idealerweise an den Anfang des Skriptes den Befehl
SetCompressor bzip2
um bspw. die bzip2-Komprimierung zu whlen. Beim zweiten Menpunkt knnen Sie die Methode
selbst whlen. Dabei wird allerdings der eben gezeigte Befehl ignoriert, bzw. es wird angezeigt,
dass dieser Befehl in dem Fall unntig ist.
Neben zlib und bzip2 untersttzt NSIS auch die lzma-Methode. Das Komprimieren mit zlib geht
meist recht schnell, dafr sind die Setups im Vergleich zu bzip2 und lzma auch meist etwas grer.
Allerdings ist das auch von den verwendeten Dateien abhngig. Dateien, die sich nur schlecht
komprimieren lassen (etwa, weil sie bereits in irgendeiner Form komprimiert sind), sollte mglichst
nicht mit bzip2 komprimiert werden. Das entstehende Setup knnte u.U. grer werden als mit der
normalen zlib-Methode.
Letztlich ist es eine Frage des Ausprobierens. Testen Sie die Methoden und entscheiden Sie sich
dann fr die effizienteste. Oder lassen Sie NSIS diese Arbeit tun, denn mit dem Menpunkt
"Compile NSIS Script (Choose Compressor)" und der Auswahl von "Best Compressor" fhrt der
Compiler eigenstndig mehrere, von der Anzahl der untersttzten Kompressionsmethoden
abhngige Kompilierungslufe durch und behlt das beste Ergebnis.

Hinweis zu bzip2 und zur modernen Oberflche


Da im nchsten Kapitel die moderne Oberflche besprochen wird, darf an dieser Stelle ein Hinweis
aus der Dokumentation nicht fehlen. Wenn Sie die bzip2-Methode verwenden, dann mssen Sie
ggf. auch zwei spezielle Makros einbinden, mit denen zu extrahierende Dateien vor anderen
Dateien im Datenblock angeordnet werden. Laut Dokumentation soll das das Setup schneller
machen.
Speziell betrifft das aber nur noch den Sprachauswahl-Dialog und die Installationsoptionen. Auf
beide Themen wird zu gegebener Zeit noch eingegangen. Im Moment sei nur gesagt, dass Sie das
Makro
!insertmacro MUI_RESERVEFILE_LANGDLL
verwenden mssen, wenn Ihr Setup mehrsprachig ist und Sie den Auswahldialog fr die Sprache
anzeigen lassen mchten (s. Seite 57). Und das Makro
!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
ist fr Sie eigentlich nur von Interesse, wenn Sie eigene Seiten in die Installationslogik einbinden (s.
Seite 59).

22

Nullsoft Scriptable Install System

Die moderne GUI


Wenn Ihnen das klassische Design von NSIS nicht gefllt, besteht in Version 2 die Mglichkeit,
eine etwas zeitgeme, Assistenten-hnliche Oberflche zu verwenden, die sich vom Aussehen
her an typischen Installern orientiert. Damit die neue Oberflche benutzt wird, ist allerdings eine
spezielle Headerdatei einzubinden
!include "MUI.nsh"
Und dann sind ein paar kleinere Eingriffe in das Skript erforderlich, weil nicht mehr alle der anfangs
gezeigten Deklarationen notwendig sind. So knnen wir normalerweise auf "ComponentText" und
"DirText" (s. Seite 6) verzichten. Der Name des Produktes wird auch hier wie in der klassischen
Oberflche gebildet
Name "INI-Cleaner fr LuckieDIPS 0.3"
Dann muss angegeben werden, welche Seiten der Assistent zeigen soll. Wir bentigen nach wie
vor die Auswahl der Komponenten und die Auswahl des Verzeichnisses. Und auch der Deinstaller
muss separat angegeben werden, da es sonst zu einer Fehlermeldung beim Erstellen des Setup
kommt.
!insertmacro
!insertmacro
!insertmacro
!insertmacro
!insertmacro
!insertmacro

MUI_PAGE_LICENSE "license.rtf"
MUI_PAGE_COMPONENTS
MUI_PAGE_DIRECTORY
MUI_PAGE_INSTFILES
MUI_UNPAGE_INSTFILES
MUI_UNPAGE_CONFIRM

Es wird im Folgenden oft von so genannten Symbolen die Rede sein, mit denen Sie
gewisse Dinge der modernen UI verndern knnen. Es wird empfohlen, alle diese
Definitionen vor dem ersten Seitenmakro (im obigen Beispiel wre das die Lizenzseite)
zu treffen. Auf diese Weise vermeiden Sie Probleme beim Kompilieren des Skriptes.

Name
MUI_PAGE_LICENSE
MUI_PAGE_COMPONENTS
MUI_PAGE_DIRECTORY
MUI_PAGE_INSTFILES
MUI_UNPAGE_INSTFILES
MUI_UNPAGE_CONFIRM

Bedeutung
Zeigt die Lizenzdatei an.
Zeigt die Komponentenauswahl an.
Zeigt die Verzeichnisauswahl an.
Zeigt den Status (Fortschritt) der Installation an.
Zeigt den Status der Deinstallation an.
Die Deinstallation muss besttigt werden

Weitere Mglichkeiten finden Sie in der NSIS-Dokumentation im Anhang A.

Bei der Definition der Seiten ist brigens auch die Reihenfolge von Bedeutung. Wenn Sie sie
beispielsweise so ndern
!insertmacro MUI_UNPAGE_INSTFILES
!insertmacro MUI_UNPAGE_CONFIRM
dann werden zuerst die Dateien entfernt, und dann werden Sie erst gefragt, ob Sie die
Deinstallation beginnen wollen. J

23

Nullsoft Scriptable Install System

Das Lizenzabkommen
Auch hier wieder die Anmerkung, dass Sie eine Checkbox oder zwei Radiobuttons verwenden
knnen, mit denen die Annahme der Lizenz besttigt werden muss. Im Normalfall sehen Sie
nmlich auch bei der modernen Oberflche nur den "Annehmen"-Button.
Fr die Checkbox definieren Sie bitte das Symbol "MUI_LICENSEPAGE_CHECKBOX" - allerdings
vor der Seite, andernfalls ist die Checkbox nmlich nicht zu sehen
!define MUI_LICENSEPAGE_CHECKBOX
!insertmacro MUI_PAGE_LICENSE "license.rtf"
Wenn Sie stattdessen die beiden Radiobuttons verwenden wollen, dann definieren Sie in Ihrem
Skript bitte das Symbol "MUI_LICENSEPAGE_RADIOBUTTONS"
!define MUI_LICENSEPAGE_RADIOBUTTONS
Beachten Sie bitte, dass Sie nur eins der beiden Symbole verwenden. Wenn Sie beide definieren,
dann wird standardmig die Checkbox verwendet.

Symbole und Bitmaps tauschen


Um das Setup zu personalisieren, knnen Sie eigene Symbole und Bitmaps definieren. Wichtig ist,
dass Sie die Angaben vor dem Aufruf der obigen Seitenmakros treffen. Ansonsten erhalten Sie die
Fehlermeldung, dass ein Symbol bereits definiert ist. Die mglichen Attribute lauten
Name
MUI_ICON
MUI_UNICON
MUI_HEADERBITMAP
MUI_SPECIALBITMAP

Bedeutung
Das Symbol der Setupdatei.
Das Symbol des Deinstallers.
Bitmap mit den Abmessungen 150x57.
Bitmap fr die Willkommens- und Abschlussseite. (Die
Standardgrafiken von NSIS haben die Mae 164x314.)

Wenn sich die Gre der Symboldateien des Installers und des Deinstallers
unterscheiden, erhalten Sie eine Fehlermeldung. Sie sollten daher nach Mglichkeit das
gleiche Symbol fr beide Programme benutzen, oder Sie mssen darauf achten, dass
die verwendeten Symbole die gleiche Dateigre haben.

24

Nullsoft Scriptable Install System

Programme nach der Installation ausfhren


Wenn Sie nach der Installation ein Programm (typischerweise Ihre Hauptanwendung) starten
lassen wollen, mssen Sie zunchst die Fertigstellen-Seite anzeigen lassen. Dazu dient das Makro
!insertmacro MUI_PAGE_FINISH
Dann knnen Sie mit dem davon abhngigen Symbol "MUI_FINISHPAGE_RUN" angeben, welche
Datei gestartet werden soll. Sind Parameter erforderlich, benutzen Sie auerdem noch das Symbol
"MUI_FINISHPAGE_RUN_PAREMETERS", beispielsweise
!define MUI_FINISHPAGE_RUN "$INSTDIR\cleanup.exe"
!define MUI_FINISHPAGE_RUN_PARAMETERS "/silent"
Optional knnen Sie auch verhindern, dass die Checkbox standardmig ausgewhlt ist.
!define MUI_FINISHPAGE_RUN_NOTCHECKED
Es ist leider nicht mglich, mehr als ein Programm anzugeben.

Nach der Installation Informationen anzeigen


Im Prinzip handelt es sich dabei um eine Variante der eben gezeigten Methode, Programme starten
zu lassen. Nur geht es hier speziell um Informationen, die fr den Benutzer wichtig sein knnen.
Also das, was man allgemein als Readme bezeichnet. Die Parameter sind hnlich den eben
gezeigten
!define MUI_FINISHPAGE_SHOWREADME "$INSTDIR\readme.txt"
!define MUI_FINISHPAGE_SHOWREADME_NOTCHECKED
Das bedeutet also, dem Anwender wird angeboten, die Datei "readme.txt" zu ffnen, wobei diese
Option allerdings nicht vorgewhlt ist.

Einen Link zu einer Webseite anzeigen


Ebenfalls mglich ist es, einen Link zu einer Webseite auf der letzten Seite anzuzeigen. Dazu
bentigen Sie die folgenden zwei Symbole
!define MUI_FINISHPAGE_LINK \
"Besuchen Sie unsere Homepage"
!define MUI_FINISHPAGE_LINK_LOCATION "http://www.irgendo-im.net"
Im ersten Symbol definieren Sie einen erklrenden Text, der dann auf der letzten Seite angezeigt
wird, und im zweiten Symbol geben Sie den Link zur gewnschten Seite an.

25

Nullsoft Scriptable Install System

Die Gruppe im Startmen selbst auswhlen


Wenn Sie dem Benutzer gestatten wollen, dass er selbst die Gruppe im Startmen auswhlen
kann, dann mssen Sie zunchst die Seite mit den vorhandenen Gruppen anzeigen lassen
Var SMFolder
!insertmacro MUI_PAGE_STARTMENU Application $SMFolder
Beachten Sie bitte die beiden rot markierten Parameter. Der erste, "Application", dient spter
zur eindeutigen Identifizierung beim Erzeugen des Ordners im Startmen. Es ist nmlich mglich,
die Seite mit den Startmengruppen mehrfach anzeigen zu lassen, so dass der Anwender fr
verschiedene Komponenten Ihrer Anwendung auch verschiedene Gruppen auswhlen kann. Dabei
ist aber jedes Mal eine andere ID zu whlen, beispielsweise
!insertmacro MUI_PAGE_STARTMENU App $AppFolder
!insertmacro MUI_PAGE_STARTMENU Help $HelpFolder
usw.
Der zweite Parameter ist die dazu gehrende Variable, die den Namen des Ordners speichern soll,
den der Anwender auswhlt. Dieser Name ist notwendig, damit die Verknpfungen spter auch
korrekt zugeordnet werden.
Wenn Sie von dieser Mglichkeit der Mehrfachauswahl Gebrauch machen, dann sollten Sie vorher
einen erklrenden Text definieren, damit der User nicht verwirrt wird, wenn nach der Auswahl der
Startmengruppe die gleiche Seite ein weiteres Mal erscheint. Benutzen Sie dazu am besten das
Symbol "MUI_STARTMENUPAGE_TEXT_TOP", dem Sie den gewnschten Text bergeben
!define MUI_STARTMENUPAGE_TEXT_TOP \
"Geben Sie hier den Ordner an in dem die Verknpfungen fr \
XY gespeichert werden sollen."
usw.
Zu beachten ist auerdem, dass der
Anwender das Erstellen einer Gruppe
standardmig mit der im Bild zu
sehenden Checkbox unterbinden kann.

Allerdings verhlt sich unser Installer auf Grund der letzten Kapitel noch unkooperativ und legt die
Verknpfungen trotzdem an. Um den Wunsch des Anwenders nun tatschlich zu bercksichtigen,
muss der Code zum Erstellen der Verknpfungen wie folgt eingeklammert werden
!insertmacro MUI_STARTMENU_WRITE_BEGIN Application
IfFileExists "$INSTDIR\cleanup.exe" 0 +3
CreateDirectory "$SMPROGRAMS\$SMFolder"
CreateShortcut "$SMPROGRAMS\$SMFolder\${PRODUCT}.lnk" \
"$INSTDIR\cleanup.exe"
!insertmacro MUI_STARTMENU_WRITE_END
Sie sehen hier die Anwendung der beiden Parameter. Allerdings mssen Sie selbst
Sorge tragen, dass Sie auch die richtige Variable benutzen. NSIS befreit Sie nicht davon.
So wre es durchaus mglich, die ID "App" zu benutzen (s. oben), die Verknpfungen
aber in dem Ordner anzulegen, der durch die Variable "$HelpFolder" identifiziert wird obwohl diese Variable eigentlich zur ID "Help" gehrt. Das ist meiner Meinung nach ein
kleiner Nachteil an bzw. in diesem System.

26

Nullsoft Scriptable Install System

Die Gruppe im Startmen muss allerdings bei der Deinstallation der Software wieder entfernt
werden knnen. Dazu ist es zunchst erforderlich, den Namen der Gruppe zu speichern. NSIS
bietet dafr die folgenden 3 Definitionen, mit denen der Installer angewiesen wird, den Namen in
der Registry zu speichern
!define MUI_STARTMENUPAGE_REGISTRY_ROOT HKLM
!define MUI_STARTMENUPAGE_REGISTRY_KEY ${UNINSTKEY}
!define MUI_STARTMENUPAGE_REGISTRY_VALUENAME "WTStartMenuFolder"
In dem Fall habe ich den Namen im "Uninstall"-Schlssel der Software speichern lassen. Wenn
Ihr Setup auch mit eingeschrnkten Benutzerrechten funktioniert und Verknpfungen anlegt, dann
sollten Sie besser "HKCU" (HKEY_CURRENT_USER) anstelle von "HKLM" verwenden.
Wenn Ihr Setup die Rechte des Anwenders prft und den Namen der Gruppe davon abhngig in
der Registry speichert, dann sollten Sie auf die o.g. Definitionen komplett verzichten und den
Namen der Gruppe selbst speichern.
Ich wrde Sie gern an das Kapitel ber die Registry verweisen (s. Seite 30). Fr den Augenblick soll
hier der Beispielaufruf fr Ihr Skript ausreichen, der im Prinzip auch nichts anderes macht als die
drei o.g. Zeilen
WriteRegStr HKLM "${UNINSTKEY}" "WTStartMenuFolder" "$SMFolder"
Die Checkbox im Bild auf der vorigen Seite lsst sich auch ausblenden. Das knnen Sie mit Hilfe
des Symbols "MUI_STARTMENUPAGE_NODISABLE" tun, das Sie vor dem Aufruf der Seite mit den
Startmengruppen definieren mssen
!define MUI_STARTMENUPAGE_NODISABLE
Das bedeutet, der Anwender kann zwar den Namen der Gruppe im Startmen frei whlen, aber er
kann das Erzeugen der Verknpfungen nicht umgehen. Ganz wichtig ist, dass Sie in diesem Fall
trotzdem die beiden, auf der letzten Seite gezeigten Makros "MUI_STARTMENU_WRITE_BEGIN"
und "MUI_STARTMENU_WRITE_END" verwenden, denn obwohl die Verknpfungen in jedem Fall
angelegt werden, wird der benutzte Ordner nur durch die Makros in der Registry gespeichert.
Wenn Sie die Makros vergessen, dann werden Sie bei der Deinstallation sptestens dann
Probleme haben, wenn der Anwender den Standardnamen Ihres Ordners verndert hat. Da der
Name nicht gespeichert wurde, ist das Entfernen der Gruppe aus dem Startmen so gut wie unmglich, und der Anwender muss die Reste selbst beseitigen.
Bei der Deinstallation benutzen Sie dann das Makro "MUI_STARTMENU_GETFOLDER" zum
Ermitteln des gespeicherten Wertes. Das Ergebnis wird in einer Variablen gespeichert, die Sie mit
angeben
!insertmacro MUI_STARTMENU_GETFOLDER Application $R0
Das Verzeichnis lsst sich dann wie gewohnt entfernen
RMDir /r "$SMPROGRAMS\$R0"
Wenn Sie auf das Makro verzichten mssen, weil Sie bspw. den Namen des Ordners in einem
anderen Schlssel gespeichert haben, dann knnen Sie auch hier wieder direkt auf die RegistryFunktionen zurckgreifen
ReadRegStr $SMFolder HKLM "${UNINSTKEY}" "WTStartMenuFolder"

27

Nullsoft Scriptable Install System

Neustart auslsen
Es gibt eine spezielle Seite des Assistenten, die dem Anwender einen Neustart anbietet. Der
Anbieter kann diesen Neustart ausfhren oder ablehnen. Leider erscheint diese Seite (bisher) nur
beim Beenden der Installation. Und das auch nur, wenn Sie eine Datei beispielsweise kopieren
oder lschen, die bereits in Benutzung ist und somit erst nach einem Neustart tatschlich kopiert
oder gelscht werden kann.
Dazu mssen Sie das Flag "/REBOOTOK" verwenden. Wenn Sie etwa eine Datei lschen wollen,
die schon vorhanden ist, in Ihrer Anwendung aber nicht mehr bentigt wird, dann schreiben Sie die
Anweisung wie folgt
Delete /REBOOTOK "Dateiname.ext"
Sollte die Datei whrend der Installation aktiv sein, kann sie natrlich nicht gelscht werden.
Stattdessen wird die Datei systemabhngig "markiert", so dass sie nach dem nchsten Neustart
entfernt wird. Und genau diesen Neustart bietet Ihnen das Setup dann nach Abschluss der
Installation auch an, wenn Sie die Abschlussseite
!insertmacro MUI_PAGE_FINISH
benutzen.
Bei der Deinstallation von benutzten Komponenten erscheint diese Seite nicht, was ich persnlich
als Nachteil empfinde, da der Benutzer so nicht unbedingt erfhrt, dass ein Neustart zum Entfernen
von einigen Dateien erforderlich ist.

28

Nullsoft Scriptable Install System

Die Beschreibungen von Komponenten anzeigen


In der modernen GUI erscheint bei der Komponentenauswahl standardmig der Hinweis, dass der
Anwender den Mauszeiger auf die Komponenten bewegen soll, um deren Beschreibungen zu
lesen. Das passiert allerdings nur, wenn Sie selbst dafr sorgen. Zuerst definieren Sie den
gewnschten Text in der folgenden Beispielform
LangString DESC_App ${LANG_GERMAN} \
"installiert ${PRODUCT}"
usw. Bei den mehrsprachigen Setups komme ich noch einmal auf "LangString" zurck. Das rot
markierte "DESC_App" ist dabei der interne Bezeichner fr den Text, den wir spter noch
bentigen. Dann mssen Sie den Sektionen jeweils interne Namen geben. Diese Namen sind im
Installer nicht zu sehen. Sie dienen nur zur eindeutigen Identifizierung einer Sektion (=
Komponente), damit auch die dazu passende Beschreibung angezeigt wird.
Nehmen wir also als Beispiel die Hauptsektion, in der das Programm installiert wird
Section "!${PRODUCT}" App
Hier ist das rot markierte "App" der interne Name. Danach bentigen Sie im Skript einen speziellen
Bereich, in dem die oben definierten Beschreibungen den einzelnen Sektionen zugeordnet werden.
Dieser Bereich beginnt mit
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
und enthlt ein Makro, das die Verbindung zwischen Beschreibung und Sektion herstellt
!insertmacro MUI_DESCRIPTION_TEXT ${App} $(DESC_App)
Wiederholen Sie diese Zeile fr alle Komponenten, die in der Auswahl angezeigt werden, und dann
schlieen Sie den Bereich mit
!insertmacro MUI_FUNCTION_DESCRIPTION_END
Und voil - wenn Sie den Mauszeiger nun
auf die entsprechende Komponente bewegen,
sehen
Sie
auch
die
entsprechende Beschreibung.

Wenn Ihnen das Beschreibungskstchen am rechten Rand nicht gefllt, knnen Sie es (wie im Bild
zu sehen) auch unterhalb der Komponentenauswahl anordnen. Definieren Sie dazu bitte das
Symbol vor dem Aufruf der Komponentenauswahl
!define MUI_COMPONENTSPAGE_SMALLDESC
Wollen Sie komplett auf die Beschreibungen verzichten, dann definieren Sie bitte stattdessen
!define MUI_COMPONENTSPAGE_NODESC
in Ihrem Skript.

29

Nullsoft Scriptable Install System

Die Registry
Dateitypen registrieren
Fr die Registry gehen wir von einem fiktiven Beispiel aus. Wir haben zwar schon entsprechende
Befehle benutzt, aber die waren nur dazu bestimmt, den Deinstaller unserer Beispielanwendung
einzutragen.
Aber zu einer richtigen Dokumentation gehrt eben auch der obligatorische Dateityp, der registriert
werden soll. Kurz noch einmal die notwendigen Schritte
1. Unter HKEY_CLASSES_ROOT muss ein Schlssel angelegt werden, der der gewnschten
Dateiendung entspricht.
2. Dessen Standardeintrag verweist auf einen zweiten Schlssel, in dem der Dateityp beschrieben wird.
3. Und darunter befinden sich auch weitere Schlssel, die die gewnschten Aktionen fr
diesen neuen Dateityp auslsen.
Wir beginnen mit dem Hauptschlssel unseres Dateityps ".xyz", der ja auch gleichzeitig die Endung
darstellt
WriteRegStr HKCR ".xyz" "" "XYZ.File"
Damit ist die Endung eingetragen, und der Standardwert dieses Schlssels verweist "XYZ.File",
den wir als nchstes anlegen
WriteRegStr HKCR "XYZ.File" "" "Meine XYZ-Datei"
Der Text "Meine XYZ-Datei", der dem Standardwert zugewiesen wird, wrde spter im Explorer als
Beschreibung des Dateityps erscheinen. Nun knnen wir ein Symbol festlegen, durch das der Typ
im Explorer dargestellt wird. Symbolreferenzen mssen unterhalb des eben erzeugten Schlssels,
in einem eigenen Schlssel namens "DefaultIcon" gesetzt werden. Wir verweisen hier auf ein
fiktives Programm, von dem wir annehmen, dass es installiert worden ist
WriteRegStr HKCR "XYZ.File\DefaultIcon" "" "$INSTDIR\XYZ-opener.exe,0"
Wrde die Datei mehr als ein Symbol enthalten, und wir mchten nicht das erste zur Anzeige verwenden, dann geben Sie nach dem Komma die Indexnummer (null-basierend) des gewnschten
Symbols an.
Es fehlt noch die Aktion, die bei einem Klick auf den Dateityp ausgelst werden soll. Wir wollen annehmen, dass sich unser fiktives Programm "XYZ-opener.exe" ffnet und den Inhalt der Datei
anzeigt.
Fr
solche
Aktionen
mssen
wir
eine
bestimmte
Schlsselfolge
einhalten:
"shell\verb\command". Davon ist lediglich das rot markierte Verb frei whlbar. Da wir ein
Programm ffnen wollen, nehmen wir "open" als Verb. Wrden Sie eine Druckfunktion schreiben,
knnten Sie "print" verwenden, usw.
ber "shell" und "command" drfen Sie sich allerdings nicht hinwegsetzen! Der Standardwert von
"shell" bezeichnet die Aktion (= ein Verweis auf das benutzte Verb), die bei einem normalen Klick
auf eine Datei ausgefhrt werden soll, und der Standardwert von "command" enthlt Pfad und
Name des Programms, das bei einer ausgewhlten Aktion ausgefhrt werden soll.

30

Nullsoft Scriptable Install System

Unsere Anweisung sieht also wie folgt aus


WriteRegStr HKCR "XYZ.File\shell\open\command" "" \
"$\"$INSTDIR\XYZ-opener.exe$\" $\"%1$\""
Von Wichtigkeit ist hierbei der rot markierte Teil. Durch "$\" wird nmlich das nachfolgende
Zeichen entwertet. Sie sehen ja selbst, dass die Anfhrungszeichen benutzt werden, um Text
einzuklammern. Soll das Anfhrungszeichen selbst aber auch Teil des Textes sein, mssen Sie
dafr sorgen, dass es nicht als Textende oder neuer -beginn missverstanden wird.
Und in diesem Fall bentigen wir die Anfhrungszeichen, weil wir unter Windows ja lange
Dateinamen und Leerzeichen in solchen verwenden knnen.
Unser Beispieldateityp enthlt nur eine Aktion, darum ist es nicht erforderlich, auch den
Standardwert von "shell" mit einem Wert zu belegen. Aber angenommen, Sie htten mehr als eine
Aktion definiert, dann knnten Sie dort (wie schon gesagt) festlegen, welche standardmig
ausgefhrt werden soll, etwa
WriteRegStr HKCR "XYZ.File\shell" "" "edit"
Dateitypen ohne Admin-Rechte registrieren
Ab Windows 2000 kann man Dateitypen auch ohne Admin-Rechte registrieren. Dazu muss man sie
allerdings in einen Schlssel unter "HKEY_CURRENT_USER" schreiben. Das bedeutet natrlich,
dass dieser Dateityp dann auch nur fr den Benutzer registriert ist, der das Setup ausgefhrt hat.
Der Vollstndigkeit halber mchte ich aber ein kurzes Beispiel zeigen
WriteRegStr HKCU "Software\Classes\.xyz" "" "XYZ.File"
WriteRegStr HKCU "Software\Classes\XYZ.File" "" "Meine XYZ-Datei"
usw. Intern benutzen Sie nach wie vor lediglich die Schlsselnamen, wie etwa "XYZ.File", beim
Anlegen desselben drfen Sie aber den neuen Prfix "Software\Classes\" nicht vergessen.
Und denken Sie bitte daran, dass das erst ab Windows 2000, XP und hher funktioniert.

DWORDs und binre Daten


NSIS kann aber nicht nur Strings in die Registry schreiben. So genannte DWORDs (REG_DWORD)
und binre Daten sind ebenfalls mglich. Fr DWORDs benutzen Sie lediglich die entsprechende
Funktion "WriteRegDword", beispielsweise
WriteRegDword HKCU "Software\Cube" "TestDWORD" "1"
Fr binre Daten (REG_BINARY) steht Ihnen "WriteRegBin" zur Verfgung, wobei Sie die Daten
formatiert als hexadezimalen String bergeben,
WriteRegBin HKCU "Software\Cube" "TestBinary" "4E534953"

31

Nullsoft Scriptable Install System

Die Rechtefrage unter Windows NT


Beachten Sie bitte, dass systembedingt spezielle Rechte erforderlich sein knnen, um Eintrge in
bestimmten Schlsseln zu hinterlegen. Dies trifft insbesondere auf die NT-Systeme (NT, 2000 und
XP) zu, bei denen beispielsweise nur Mitglieder der Gruppe der Administratoren in den
Registryschlssel "HKEY_LOCAL_MACHINE" schreiben drfen.
Das Schreiben im genannten Schlssel kann aber notwendig sein, wenn Ihre Anwendungen unabhngig vom angemeldeten Benutzer bestimmte Einstellungen bentigen. Sie sollten daher die
Rechte des angemeldeten Benutzers prfen und das Setup ggf. abbrechen.
Im Kapitel "Die eingebaute Skriptsprache" finden Sie eine Lsung, wie Sie vor der Installation
prfen knnen, welche Berechtigungen der angemeldete Benutzer hat.
Der Benutzertyp "Hauptbenutzer" verfgt ebenfalls ber erweiterte Rechte, die
mglicherweise fr Ihr Setup schon ausreichen.
Es steht Ihnen frei, das Schreiben auch einmal ohne Administrator-Rechte zu versuchen.
Ist Ihr Windows korrekt eingestellt, dann sollte normalerweise eine Fehlermeldung beim
Versuch er-scheinen, in den Schlssel "HKEY_LOCAL_MACHINE" zu schreiben.
Gedanken wrde ich mir an Ihrer Stelle machen, wenn der Schreibversuch funktioniert.
In dem Fall ist Ihr System zu lax eingestellt. Sie sollten immer bedenken, dass das, was
Sie tun knnen, auch ein Virus oder hnlich schdliches Programm tun kann, das im
selben Kontext luft.

32

Nullsoft Scriptable Install System

Selbst aufrumen
Wie ich bereits im Kapitel ber den Deinstaller schrieb mssen Sie sich selbst darum kmmern,
dass die Spuren Ihrer Anwendung verschwinden. Das mag man als Manko auffassen, weil die
anderen bekannten Installer (MSI, Inno Setup, usw.) die entsprechenden Funktionen von selbst
anbieten. Auf der anderen Seite haben Sie hier die vllige Kontrolle. Das bedeutet aber wiederum,
dass Sie sorgfltig vorgehen mssen, um nicht versehentlich zu viel oder gar die falschen Dinge zu
entfernen.
Wenn wir bei unseren zwei Beispieleintrgen und dem Dateityp bleiben, dann mssen wir bei der
Deinstallation (in der Sektion "Uninstall"; vgl. auch Seite 12ff) dafr sorgen, dass die Eintrge
und Schlssel wieder verschwinden.
Am einfachsten ist dies noch beim Dateityp, da wir hier lediglich den Schlssel mit der Endung und
den entsprechenden Verweisschlssel entfernen mssen. Die evtl. vorhandenen Werte und
untergeordneten Schlssel werden dadurch automatisch entfernt.
DeleteRegKey HKCR ".xyz"
DeleteRegKey HKCR "XYZ.File"
Es gibt allerdings die Mglichkeit, das Lschen des Schlssels davon abhngig zu machen, dass er
leer ist. Das ist ntzlich, wenn Sie mehrere Anwendungen verffentlichen, deren
Grundeinstellungen beispielsweise in einem Schlssel hinterlegt werden, den Sie nach Ihrer Firma
benannt haben.
Wrden Sie diesen Firmenschlssel ohne Rcksicht entfernen, verschwinden dabei
mglicherweise auch die Eintrge der anderen Programme, die der Anwender aber noch behalten
und weiter nutzen mchte.
Also sollten Sie zunchst die notwendigen Schlssel oder Eintrge entfernen und dann versuchen,
den Schlssel zu lschen, wobei Sie aber den Parameter "/ifempty" angeben
DeleteRegValue HKCU "Software\Cube" "TestDWORD"
DeleteRegValue HKCU "Software\Cube" "TestBinary"
DeleteRegKey /ifempty HKCU "Software\Cube"
Nur wenn der Schlssel keine weiteren Daten mehr enthlt, wird er entfernt.

33

Nullsoft Scriptable Install System

INI-Dateien
Das Anlegen und Lschen von INI-Dateien bzw. von Eintrgen in solchen Dateien ist natrlich auch
mit NSIS mglich. Zum Anlegen von Eintrgen benutzt man "WriteIniStr" mit folgender Syntax
WriteIniStr "$INSTDIR\MyConfig.ini" "general settings" \
"path" "$INSTDIR"
UserInfo::GetName
Pop $0
WriteIniStr "$INSTDIR\MyConfig.ini" "general settings" "user" "$0"
FlushINI
Diese Anweisungen wrden die Datei "MyConfig.ini" im Installationsordner erstellen und den
Pfad- sowie den Benutzernamen des angemeldeten Benutzers eintragen.
Auf das UserInfo-Plugin komme ich im Kapitel "Die eingebaute Skriptsprache" noch
einmal zurck.

Auch hier gilt wieder, dass Sie solche Eintrge beim Deinstallieren der Anwendung selbst entfernen
mssen. Im obigen Fall ist es natrlich recht einfach, weil wir lediglich die erzeugte INI-Datei
lschen lassen mssen.
Zustzlich mchte ich noch zeigen, wie man eine bestehende INI-Datei erweitert. Nehmen wir als
Beispiel an, dass Sie die "win.ini" erweitern mssen. Mit der folgenden Anweisung wird eine
neue Sektion ergnzt und mit einem Wert gefllt
WriteIniStr "$WINDIR\win.ini" "INI-Cleaner" \
"test_eintrag" "Hallo, win.ini!"
Hier drfen wir die INI-Datei natrlich nicht einfach so lschen. Wenn wir lediglich den von uns angelegten Eintrag entfernen wollen, den Rest unserer eigenen Sektion aber intakt lassen mchten,
dann verwenden wir "DeleteIniStr"
DeleteIniStr "$WINDIR\win.ini" "INI-Cleaner" \
"test_eintrag"
Wenn Sie die gesamte Sektion entfernen wollen, dann benutzen Sie "DeleteIniSec"
DeleteIniSec "$WINDIR\win.ini" "INI-Cleaner"
Sie sollten INI-Dateien nach Mglichkeit nicht mehr im Windows- oder im Systemordner
ablegen. Nicht nur, dass Microsoft dieses Verhalten von Programmen missbilligt, speziell
auf NT-Systemen kann es dabei auf Grund fehlender Berechtigungen (hnlich wie bei
der Registry) zu Problemen kommen.
Darum sollten Sie Ihre INI-Dateien bevorzugt im Ordner der Anwendung ablegen, bzw.
diese in benutzerabhngigen oder fr alle Benutzer zugnglichen Ordnern speichern.
Dieses Beispiel finden Sie im beiliegenden Skript "regini.nsi".

34

Nullsoft Scriptable Install System

Upgrades
Wenn Sie die anderen Dokumentationen (ber den MSI und Inno Setup) kennen, dann wissen Sie
sicher, dass dort auch Upgrades angesprochen wurden. Ich persnlich halte das fr ein wichtiges
Thema, denn Sie werden ja nicht nur eine einzige Version Ihrer Anwendung verffentlichen und das
Projekt dann einstellen.
Und ich glaube auch nicht, dass Sie sich bei jeder neuen Version Ihrer Anwendung fr einen neuen
Installer entscheiden. Wenn Sie mit dem Microsoft Installer arbeiten, dann werden Sie das sicher
ber mehr als eine Version hinweg tun. Und bei Inno Setup oder eben NSIS drfte dies auch so
sein.
Und hier muss man leider sagen, dass NSIS nicht von Haus aus Upgrade-freundlich ist. Eine
Funktion wie beim MSI oder Inno Setup, mit der installierte ltere Versionen automatisch gefunden
werden, existiert meinem Wissen nach leider nicht.
Allerdings gibt es ein paar Mglichkeiten, dieses Problem zumindest teilweise zu umgehen. Das
bedeutet allerdings, dass Sie von der ersten Version Ihrer Anwendung das Verhalten von Upgrades
einplanen mssen, damit sich das Setup richtig verhlt.
Was sind typische Verhaltensweisen?
1. Sie bieten eine neue Version Ihres Produktes an, die vom Anwender auch bezogen wird.
Bei der Installation muss die neue Version nun nach evtl. vorhandenen lteren Versionen
suchen, diese ggf. entfernen oder aktualisieren.
2. Wenn der Benutzer die neue Version installiert hat, aber nicht mehr daran denkt und eine
ltere Version installieren will, dann muss diese ltere Version erkennen, dass eine
aktuellere Version installiert ist und sich beenden.
Speziell Punkt 2 ist ein bisschen trickreich. Hier hat der Microsoft Installer die besseren Karten, weil
er diese Technik von Haus aus untersttzt. Was knnen Sie nun tun?
1. Sie knnten den Pfad der Anwendung beispielsweise in der Registry sichern. NSIS bietet
die Mglichkeit, ber das Attribut "InstallDirRegKey" den entsprechenden Schlssel
auszulesen
InstallDirRegKey HKLM "Software\Ihre Firma\Ihre Anwendung"
"AppPath"
Wird der Eintrag (hier "AppPath") in diesem Schlssel gefunden, wird das in
"InstallDir" gesetzte Standardverzeichnis angepasst, und Ihre Anwendung lsst sich
schon einmal in den Ordner der alten Version installieren.
Notfalls knnen Sie auch den "UninstallString"-Wert angeben. Das Setup entfernt
den Dateinamen des Deinstallers automatisch. Allerdings setzt das voraus, dass sich der
Deinstaller im selben Ordner wie Ihre Anwendung befindet.
2. Sie knnten den "Uninstall"-Schlssel in jeder Version Ihrer Anwendung beibehalten
und dann entsprechend prfen. Wenn der Schlssel bereits existiert, dann kann Ihr Setup
weitere Schritte fr eine genauere Versionsprfung einleiten.
3. Diese Versionsprfung lsst sich auf mehrere Arten durchfhren
a. Eine Mglichkeit wre, dass Sie eine bestimmte Datei Ihrer Anwendung (die immer
installiert sein muss) zu finden versuchen. Sofern diese Datei auch
Versionsangaben enthlt, knnen Sie diese mit im Setup gespeicherten Angaben
vergleichen und wissen so, ob die installierte Anwendung lter oder neuer ist. Die
Anwendung dieser Methode finden Sie im Kapitel "Die eingebaute Skriptsprache".
35

Nullsoft Scriptable Install System

b. Eine zweite Mglichkeit wre, dass Sie die Versionsnummer der Anwendung selbst
in der Registry speichern (etwa im "Uninstall"-Schlssel, wie dies auch der MSI
macht) und diese dann mit der Version des Setup vergleichen. Auch so knnen Sie
ermitteln, welche Version aktueller ist.
Eine hundertprozentige Sicherheit werden Sie mit solch einfachen Beispielen natrlich nicht
erreichen. Es gibt immer Mglichkeiten, solche Schutz- und Prfmechanismen auszuhebeln. Aber
sie in jedem Fall besser als gar keine Prfung.
Ich mchte nicht vorgreifen, darum demonstriere ich einen Ansatz fr o.g. Punkt 3b im
Kapitel "Idee fr eine Upgradefunktion" (s. Seite 76), weil ich nmlich entsprechende
Funktionen benutzen muss.

36

Nullsoft Scriptable Install System

Mehrbenutzer-Umgebungen
Standardmig installiert NSIS Programme nur fr den angemeldeten Benutzer. Wenn Sie
allerdings Ihr Programm fr alle Benutzer zur Verfgung stellen mchten, mssen Sie den Kontext
des Installers ndern. Dazu gengt ein einfacher Befehl, den Sie beispielsweise beim Abfragen der
Admin-Rechte (s. Kapitel "Die eingebaute Skriptsprache") einfgen knnen
SetShellVarContext "all"
So wre es durchaus mglich, einem Benutzer mit eingeschrnkten Rechten zumindest das
Kopieren der Daten und das Anlegen von persnlichen Verknpfungen zu gestatten. Wenn der
Benutzer einen Ordner whlt, auf den er Schreibzugriff hat, und wenn Sie in diesem Fall auf die
Erstellung des Deinstallers verzichten, dann spricht nichts dagegen.
Wenn Ihr Programm auf diese Weise auch fr normale Benutzerkonten zur Verfgung
steht, knnen Sie trotzdem einen Deinstaller anlegen. Sie mssen lediglich auf den
HKLM-Eintrag in der Registry verzichten, mit dem die Anwendung in der
Systemsteuerung erscheint. Stattdessen knnten Sie eine Verknpfung fr den
Deinstaller im Startmen anlegen. So hat auch ein Anwender ohne erweiterte Rechte die
Mglichkeit, die kopierten Dateien entfernen zu lassen.
Und sobald ein Benutzer der Gruppe der Administratoren Ihre Anwendung installiert, rufen Sie den
o.g. Befehl auf, und der Installer richtet Verknpfungen u.. so ein, dass sie allen Benutzern zur
Verfgung stehen.
Beachten Sie bitte, dass Sie dies dann aber auch fr den Deinstaller tun mssen. Sonst
bleiben die Verknpfungen im Startmen usw. zurck, weil der Deinstaller ebenfalls
standardmig nur im Kontext des gerade angemeldeten Benutzers aktiv wird.
Spezielle Variablen fr alle angemeldeten Benutzer, wie etwa bei Inno Setup, sind somit
bei NSIS nicht erforderlich.

37

Nullsoft Scriptable Install System

Die eingebaute Skriptsprache


Das Thema wird sicher etwas umfangreicher werden, weil die Skriptsprache die grte
Strke von NSIS ist. Sie knnen eine Menge Dinge damit anstellen. Da ich selbst (um es
mit den Worten von Markus Fuchs zu sagen) "erst an der Oberflche kratze", wird
dieses Kapitel sicher nicht alle Geheimnisse lsen. Aber ich arbeite daran

Das Betriebssystem ermitteln


Wie ich eingangs schon sagte, luft mein Beispielprogramm nur unter Windows NT und hher. Ich
erlaube dem Anwender zwar trotzdem die Installation, aber damit berhaupt die Abfrage erscheint,
muss ich erst einmal ermitteln, unter welchem Windows der Installer luft.
Dazu gibt es einen relativ einfachen Trick. Wir fragen einfach den Wert von "CurrentVersion"
aus der Registry ab, benutzen dafr aber den "Windows NT"-Schlssel, der auf 9x-Plattformen evtl.
vorhanden ist, aber den genannten Wert nicht enthlt.
ReadRegStr $R0 HKLM \
"SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion
StrCmp $R0 "" Win9x
Trifft die Bedingung zu, wird das Skript bei der Sprungmarke "Win9x" fortgesetzt. Andernfalls luft
das Skript normal weiter und prft das Benutzerkonto desjenigen, der gerade die Installation
ausfhrt.

Sektionen deaktivieren und verschwinden lassen


Widmen wir uns aber dem "Win9x"-Teil des Skriptes. Hier wird der Anwender gefragt, ob er die
Installation trotz Windows 9x-Plattform durchfhren mchte
Win9x:
MessageBox MB_YESNO|MB_ICONQUESTION \
"Dieses Programm ist nur unter Windows NT oder hher lauffhig. \
Trotzdem installieren?" IDYES +2
Abort
Besttigt er mit Ja, werden die beiden ersten Komponenten aus dem Installer ausgeblendet. Er
kann also nur noch den Quellcode installieren, da ihm das kompilierte Programm auf seiner
Plattform ohnehin nicht viel nutzt.
Damit dieses Deaktivieren und Verstecken auch klappt, bentigen wir zuerst eine Headerdatei von
NSIS, die wir in unser Skript einbinden
!include Sections.nsh
Diese Headerdatei enthlt Definitionen, von denen wir speziell die Attribute zum ndern des Status
verwenden wollen.
Auerdem brauchen die Sektionen, die wir verbergen wollen, noch interne Namen, mit denen wir
sie ansprechen knnen. Da wir das aber bereits bei der Anzeige der Beschreibungen in der
modernen Oberflche hatten, ist es aber nicht neu
Section "!${NAME}" App

38

Nullsoft Scriptable Install System

Mit Hilfe der Funktion "SectionGetFlags" knnen wir nun die aktuell eingestellten Attribute fr
eine Sektion ermitteln. Als Parameter bergeben wir dabei den eben definierten internen Namen
der Sektion und die Variable "$0". Im folgenden Beispiel ermitteln wir die Attribute der ersten
Sektion
SectionGetFlags ${App} $0
Wenn wir die Attribute ermittelt haben, whlen wir die Sektion zuerst ab. Das heit, die
Komponenten dieser Sektion lassen sich bereits nicht mehr installieren. Dazu benutzen wir die
Funktion "IntOp", in etwa vergleichbar mit einer Wertzuweisung. Das heit, zwei Werte werden
miteinander kombiniert. Uns stehen dabei sowohl die Grundrechenarten als auch boolsche
Verknpfungen zur Verfgung.
Wer Erfahrung mit einer Programmiersprache hat, ist leicht im Vorteil, weil die Eingewhnung nicht
so schwer ist. Wie dem auch sei, um die Sektion abzuwhlen, mssen wir ein Bit entfernen. Das
macht man blicherweise mit and not, was in der NSIS-Syntax so aussieht
IntOp $0 $0 & !${SECTION_OFF}
Zugegeben, das ist etwas verwirrend, denn "${SECTION_OFF}" legt ja eigentlich nahe, dass das
Bit hinzugefgt werden muss, um die Sektion zu deaktivieren. Wenn Sie es allerdings mit or
probieren, dann werden Sie feststellen, dass der Haken in der Komponentenauswahl bleibt.
Es funktioniert daher tatschlich nur auf die eben gezeigte Weise (wenn es kein Bug im NSIS ist
J).
Wir setzen die deaktivierte Sektion zur Sicherheit noch auf Read-only. Das bedeutet, der Benutzer
hat (selbst wenn die Komponente sichtbar wre) keine Chance, am abgewhlten Status etwas zu
ndern. Hier mssen wir ein Bit hinzufgen, was typischerweise mit or gemacht wird
IntOp $0 $0 | ${SF_RO}
Die neuen Attribute weisen wir der entsprechenden Sektion mit der Funktion "SectionSetFlags"
wieder zu
SectionSetFlags ${App} $0
Bleibt als letzter Schritt nur noch, die Komponente aus dem Installer zu entfernen, so dass der Anwender sie erst gar nicht sieht. Erinnern Sie sich bitte an den Abschnitt auf Seite 10. Dort wurde
gesagt, dass eine Sektion unsichtbar ist, wenn sie keinen Namen hat, bzw. wenn dieser mit einem
Minus beginnt.
In diesem Fall mssen wir aber beim Leerstring bleiben, da das Minus als Kennung fr eine Subsektion benutzt wird. Mit Hilfe von "SectionSetText" bergeben wir also einfach einen leeren String
an unsere Sektion
SectionSetText ${App} ""
Wenn Sie das nun fr die DesktopVerknpfung wiederholen und das
Skript dann testen, passiert unter
Windows 98 beispielsweise das hier

Ein kleines Problem gibt es jetzt aber noch. Erinnern Sie sich bitte an die Zuweisung der
Installationstypen. Programm und Desktop-Verknpfung gehrten ursprnglich zu allen Typen, der
Quellcode war dagegen nur bei der vollstndigen Installation ausgewhlt.

39

Nullsoft Scriptable Install System

Weil wir jetzt aber die beiden Hauptkomponenten ausgeblendet haben, wrde bei der Auswahl der
kompakten Installation pltzlich gar nichts mehr markiert sein. Das sieht nicht gut aus, und darum
mssen wir das noch ndern.
Wir geben also zuerst auch der Sektion, die den Quellcode des Programms installiert, einen
eigenen
internen
Namen,
"AppSource"
beispielsweise.
Dann
benutzen
wir
"SectionSetInstTypes" und weisen der Sektion den Wert 3 zu
SectionSetInstTypes ${AppSource} 3
Der Wert 3 ergibt sich in dem Fall aus der binren Verknpfung der beiden Installationstypen, die
wir erzeugt haben. Wenn Sie sich bitte erinnern wollen: es wurde gesagt, dass der erste
Installationstyp die Nummer Eins hat, der zweite demzufolge die Nummer Zwei (vgl. Seite 16). Die
binre Maske fr unsere beiden Typen sieht daher so aus
00000011
Rechnen Sie diesen Wert entsprechend um, erhalten Sie die 3. Zur Verdeutlichung: Nehmen wir
an, wir htten fnf verschiedene Installationstypen, und wir mchten, dass die Sektion im ersten,
dritten und fnften Typ ausgewhlt ist. Dann she die Maske so aus
00010101
was den Wert 21 (1 + 4 + 16) ergeben wrde.
Hinweis
Die Headerdatei "Sections.nsh" enthlt brigens fertige Funktionen, mit denen Sie sich das
Leben leichter machen knnen. Wenn Sie eine Sektion deaktivieren wollen, dann benutzen Sie
ganz einfach das Makro "UnselectSection" wie folgt
!insertmacro UnselectSection "${App}"
Das Gegenstck dazu ist selbstverstndlich
!insertmacro SelectSection "${App}"
Wenn Sie das Read only-Flag setzen wollen, benutzen Sie das Makro "SetSectionFlag" wie
folgt
!insertmacro SetSectionFlag "${App}" "${SF_RO}"

40

Nullsoft Scriptable Install System

Bin ich Administrator, oder was?


Zum Ermitteln der Benutzerrechte verwenden wir eine der beiliegenden Plugin-DLLs. Die wird von
NSIS automatisch eingebunden, sobald wir eine ihrer Funktionen verwenden. In dem Fall ist es die
Funktion "GetAccountType". Weil es sich aber um eine Funktion aus einer externen DLL und
nicht von NSIS handelt, mssen Sie die benutzte DLL mit angeben.
UserInfo::GetAccountType
Diese Funktion ermittelt den Kontotyp des aktuell angemeldeten Benutzers und legt das Ergebnis
auf dem Stack ab. Mit Hilfe von "Pop" holen wir das Ergebnis vom Stack und weisen es der
Variablen "$0" zu
Pop $0
Nun knnen wir einen normalen Stringvergleich durchfhren, wobei wir einen der folgenden Typen
zur Auswahl haben
Name
Guest
User
Power
Admin

Bedeutung
Gast
Benutzer
Hauptbenutzer
Administrator

In unserem Fall also


StrCmp $0 "Admin" done NoAdmin
"StrCmp" vergleicht zwei Strings miteinander. Die Schreibweise (Gro- und Kleinbuchstaben) spielt
dabei keine Rolle. Fllt der Vergleich positiv aus, wird die erste angegebene Sprungmarke
verwendet. Ist der Vergleich negativ, wird das Skript bei der zweiten Sprungmarke fortgesetzt.
Fehlen dem Benutzer also die notwendigen Rechte, springt der
Installer zu "NoAdmin", zeigt eine
Hinweismeldung an und beendet
sich dann.

41

Nullsoft Scriptable Install System

Dialogboxen
Damit knnen wir uns ansehen, wie solche Meldungen erzeugt werden. Dazu wird ganz einfach nur
der Befehl "MessageBox" verwendet. Der erste Parameter definiert Buttons und Icons, die Sie
sehen wollen, der zweite Parameter ist der Text. Im Fall der obigen Meldung sieht das dann so aus
MessageBox MB_OK|MB_ICONEXCLAMATION \
"Zur Installation sind Administratorrechte erforderlich"
Auch hier haben Sie einen Vorteil, wenn Sie bereits mit irgendeiner Programmiersprache gearbeitet
haben, denn dann sind Ihnen Werte wie MB_OK und MB_ICONEXCLAMATION bekannt. Wenn Sie
keine Erfahrung haben, dann finden Sie in der Dokumentation eine Auflistung der mglichen Werte.
Die Dialogbox untersttzt aber auch einfache Benutzerabfragen wie Ja, Nein, usw. Als Beispiel soll
der Dialog unter Windows 98 erwhnt werden. Hier wird der Anwender darber informiert, dass das
Programm eigentlich nur unter NT und hher luft. Er kann aber zumindest den Quellcode
installieren lassen, wenn er dies wnscht und seinem Wunsch mit Ja Ausdruck verleiht. J
Programmierer kennen die Vorgehensweise sicherlich schon. Sie erzeugen nach obigem Muster
wieder eine Dialogbox mit den bentigten Buttons (MB_YESNO) und geben den Text an. Hier ist
dann allerdings der Rckgabewert der Dialogbox von Interesse, der jeweils von den benutzten
Buttons abhngt.
Wir haben die Buttons Ja und Nein verwendet, daher lautet der Rckgabewert IDYES oder IDNO.
Bei einem OK-Button wre der Rckgabewert dann IDOK, usw. Auch hier finden Sie die mglichen
Werte in der Dokumentation von NSIS.
MessageBox MB_YESNO|MB_ICONQUESTION \
"Dieses Programm ist nur unter Windows NT oder hher lauffhig. \
Trotzdem installieren?" IDYES +2
Abort
Das Prinzip entspricht den bereits angesprochenen Vergleichen ("IfFileExists", beispielsweise)
und Sprngen. Wir vergleichen im Prinzip mit obiger Anweisung das Rckgabeergebnis des
Dialogs mit dem Wert IDYES. Fllt der Vergleich positiv aus, berspringen wir mit +2 den Abbruch
des Skriptes und gestatten dem Anwender die eingeschrnkte Installation unter Windows 9x.
Und mehr gibt es zu den Dialogboxen eigentlich auch nicht zu sagen.

42

Nullsoft Scriptable Install System

Die NSIS-Variablen
NSIS verfgt ber 18 so genannte Benutzervariablen: $0 - $9 und $R0 - $R9. In der Dokumentation
wird empfohlen "$R0" bis "$R9" als lokale Register und "$0" bis "$9" als globale Variablen zu
verwenden. Ab NSIS 2.0 Beta 4 knnen Sie auch eigene Variablen deklarieren, womit die
Einschrnkungen entfallen. Die Deklaration solcher Variablen sieht wie folgt aus
Var Meine Variable
Sie knnen diese Variablen mit Werten belegen, Werte abfragen, usw.
Nachfolgend mchte ich ein paar Beispiele zeigen.

Push, Pop und Exch


Will man Variablen zuweisen oder ihre Werte ermitteln, macht man in NSIS auch Bekanntschaft mit
dem Stack. Der Stack funktioniert nach dem LIFO-Prinzip (last in, first out - zuletzt rein, zuerst
raus), was sich mit einem einfachen Beispiel schnell verdeutlichen lsst. Wir legen zunchst vier
Werte im Stack ab. Dazu benutzen wir die Anweisung "Push"
Push
Push
Push
Push

"1"
"2"
"3"
"4"

Mit Hilfe von "Pop" holen wir sie nacheinander wieder vom Stack und lassen uns das Ergebnis
anzeigen
Pop
Pop
Pop
Pop

$0
$1
$2
$3

MessageBox MB_OK "$0 -> $1 -> $2 -> $3"


wzbw (was zu beweisen war), wie mein Mathelehrer immer zu sagen pflegte J
Man kann mit "Exch" die Werte im Stack auch tauschen. Ruft man den Befehl ohne weitere
Angabe auf, werden die beiden obersten Werte im Stack vertauscht. Um also beim Beispiel zu
bleiben
Push
Push
Push
Push
Exch

"1"
"2"
"3"
"4"

Pop $0
Pop $1
MessageBox MB_OK "$0 -> $1"
Die unteren beiden Stackwerte interessieren uns hier nicht, weil sie sich nicht verndert haben.

43

Nullsoft Scriptable Install System

Aber auch das geht. Dazu bergibt man "Exch" den Index (null-basierend) des gewnschten
Wertes. Um etwa den obersten und den untersten Wert zu vertauschen, lautet die Anweisung nach
dem Fllen des Stacks
Exch 3
Pop
Pop
Pop
Pop

$0
$1
$2
$3

MessageBox MB_OK "$0 -> $1 -> $2 -> $3"


Beachten Sie bitte den Indexwert 3 beim Aufruf von "Exch"! Weisen Sie einen ungltigen
Wert zu, erhalten Sie eine Fehlermeldung!

Strings
Die Zuweisung von Werten geschieht bei NSIS hauptschlich mit "StrCpy". Obwohl es sich dabei
hauptschlich um eine Stringroutine handelt, kann man sie auch zur Zuweisung von IntegerWerten benutzen. blicherweise aber wird man wohl so arbeiten
StrCpy $0 "NSIS-Dokumentation"
StrLen $1 "$0"
MessageBox MB_OK \
"$\"$0$\" enthlt $1 Zeichen"

44

Nullsoft Scriptable Install System

IntOp und IntCmp


Den Befehl "IntOp" habe ich ebenfalls schon erwhnt, als es darum ging, die Eigenschaften von
Sektionen zu verndern. Wie angesprochen, knnen Sie damit auch normal rechnen. Dazu weisen
Sie einer NSIS-Variablen zunchst einen Ausgangswert zu, mit dem Sie arbeiten wollen. Als
Beispiel die einfachste Variante: die Addition
StrCpy $0 1
IntOp $0 $0 + 1
MessageBox MB_OK "$0"

Dass es aber auch anspruchsvoller sein darf, zeigt das folgende kleine Beispiel. Wir benutzen das
Ergebnis unserer Addition und multiplizieren es mit 12. Dann dividieren wir es zuerst durch 5 und
weisen das Ergebnis einer neuen Variable zu. Eine dritte Variable muss fr eine modulo-Operation
herhalten, damit wir den Rest der Division ermitteln knnen
IntOp $0 $0 * 12
IntOp $1 $0 / 5
IntOp $2 $0 % 5
MessageBox MB_OK \
"$0 dividiert durch 5 = $1 -> Rest $2"
Weitere Informationen finden Sie in der Dokumentation im Kapitel 4 unter dem Stichwort
"Integer Support".

Mit "IntCmp" knnen Sie Integer-Werte vergleichen. Dabei steht an erster Stelle der Sprung, fr
den Fall, dass die Werte identisch sind. An zweiter Stelle folgt der Sprung, wenn der erste
bergebene Wert kleiner ist. Und zuletzt folgt der Sprung, wenn der erste Wert grer ist.
Notwendig ist dabei eigentlich nur Sprung im Fall der Gleichheit. Die beiden anderen Sprnge sind
optionale Angaben.
StrCpy $0 "1"
StrCpy $1 "2"
IntCmp $0 $1 0 +3 +5
MessageBox MB_OK "$0 ist gleich $1"
goto done
MessageBox MB_OK "$0 ist kleiner als $1"
goto done
MessageBox MB_OK "$0 ist grer als $1"
done:
Sie finden all diese kleinen Spielereien im beiliegenden Skript "stack.nsi".

45

Nullsoft Scriptable Install System

Registryschlssel auflisten
In diesem Kapitel mchte ich kurz zeigen, wie man Schlssel in der Registry auflisten und der
Reihe nach durchsuchen kann. Dazu verwende ich die Liste der installierten Software, die der
Installer (mglichst mit dem Klarnamen aus der Systemsteuerung) anzeigen soll. Um den Zugriff
einfacher zu gestalten habe ich zunchst ein Symbol deklariert
!define UNINSTREGKEY \
"Software\Microsoft\Windows\CurrentVersion\Uninstall"
Dann setzen wir zunchst den Zhler (in der Variablen "$0") auf Null und deklarieren eine Sprungmarke,
StrCpy $0 0
Loop:
Das Auflisten der Schlssel erfolgt mit der Funktion "EnumRegKey", die zuerst eine Variable
erwartet, die den gefundenen Schlsselnamen zugewiesen bekommen soll. Danach folgen Root
und Schlssel in der Registry. Am Schluss steht dann der Index; quasi der eben erzeugte Zhler
EnumRegKey $1 HKLM "${UNINSTREGKEY}" $0
StrCmp $1 "" Done
Wird ein Leerstring zurckgeliefert, bedeutet das, es gibt keine weiteren Schlssel mehr, und wir
springen zu "Done", womit die Schleife beendet wre.
Im Idealfall haben wir allerdings einen Schlssel ermittelt, den wir nun ffnen, damit wir den
Klarnamen der installierten Software erhalten. Sollte es keinen Klarnamen geben, versuchen wir
unser Glck noch einmal mit dem so genannten "QuietDisplayName", der von Microsoft sehr
gern benutzt wird, um bestimmte Komponenten aus der Systemsteuerung auszublenden
ReadRegStr $2 HKLM "${UNINSTREGKEY}\$1" "DisplayName"
StrCmp $2 "" 0 +2
ReadRegStr $2 HKLM "${UNINSTREGKEY}\$1" "QuietDisplayName"
Beides (Schlssel- und Klarnamen) lassen wir uns dann anzeigen
DetailPrint "$1 ($2)"
Wir erhhen den Zhler um Eins und springen zurck zu "Loop", um den nchsten Schlssel zu
ermitteln.
IntOp $0 $0 + 1
goto Loop
Ansonsten folgt nur noch der Aussprungpunkt "Done", mit dem die Schleife (wie bereits erwhnt)
beendet wird.
Dieses Beispiel finden Sie in der beiliegenden Datei "regini.nsi".

46

Nullsoft Scriptable Install System

Dateien erzeugen, ergnzen und ihren Inhalt anzeigen


Eine ebenfalls interessante Mglichkeit von NSIS ist das Anlegen von Dateien. Natrlich kann man
bestehende Dateien auch ergnzen bzw. ffnen und ihren Inhalt anzeigen. Beginnen wir mit dem
ersten Fall.
Eine neue Datei erzeugen
Dazu bentigen wir den Befehl "FileOpen", der als Parameter eine Benutzervariable, den
Dateinamen und den Modus bentigt, in dem wir die Datei ffnen wollen
FileOpen $0 "filetest.txt" "w"
Modus
w
a
r

Bedeutung
Datei wird zum Schreiben geffnet. Wenn die Datei bereits existiert, wird ihr Inhalt
dadurch gelscht.
Datei wird zum Lesen und Schreiben geffnet. Der Inhalt existierender Dateien
bleibt erhalten.
Datei wird zum Lesen geffnet.

Konnte die Datei nicht geffnet oder erzeugt werden, wird die angegebene Variable auf einen
Leerstring gesetzt. Sie sollten daher unbedingt eine Kontrolle benutzen und die Dateiroutinen ggf.
berspringen. Im folgenden Beispiel wird vorausgesetzt, dass ein Sprungziel "Done" existiert, das
im Fehlerfall angesteuert wird
StrCmp $0 "" Done
Wenn die Datei wie in unserem Fall erzeugt werden konnte, dann schreiben wir mit "FileWrite"
einen beliebigen String hinein. Der Befehl bentigt natrlich noch die zuvor zugewiesene Variable,
FileWrite $0 "Hallo, Welt!"
Wichtig zu wissen ist hierbei, dass Strings ohne Zeilenumbruch geschrieben werden. Wenn Sie
einen Zeilenumbruch bentigen, dann mssen Sie zustzlich angeben, wobei allerdings die NSISSyntax zu benutzen ist
FileWrite $0 "Hallo, Welt!$\r$\n"
Damit knnen wir die Datei auch schon schlieen
FileClose $0
Wenn Sie binre Daten schreiben mssen, dann geht das mit Hilfe von "FileWriteByte". Allerdings
ist das etwas umstndlich, weil sie immer nur ein Byte schreiben knnen. Der obige Zeilenumbruch
she damit wie folgt aus
FileWriteByte $0 13
FileWriteByte $0 10

47

Nullsoft Scriptable Install System

Textzeilen an den bestehenden Inhalt anhngen


Auch hier muss die Datei zunchst geffnet werden - diesmal allerdings im Modus "a" (append),
weil wir den bereits bestehenden Inhalt behalten wollen. Wenn die Datei geffnet werden konnte,
suchen wir mit "FileSeek" ihr Ende. Normalerweise erwartet dieser Befehl als zweiten Parameter
einen relativen Offset, da wir aber als Modus (das ist der dritte Parameter) das Schlsselwort "END"
nehmen, spielt der Offset hier keine Rolle und kann Null sein.
FileSeek $0 0 END
Der Rest ist mit dem eben gezeigten Beispiel identisch. Sie hngen den oder die gewnschten
neuen Textzeilen an, ergnzen ggf. den Zeilenumbruch, und dann schlieen Sie die Datei wieder.
Den Inhalt der Datei anzeigen
Auch hier muss die Datei natrlich zunchst geffnet werden. Als Modus whlen wir diesmal "r".
Da der Zeiger auf den Dateianfang gesetzt wird, kann sofort mit dem Auslesen der einzelnen Zeilen
begonnen werden.
Dazu benutzt man "FileRead". Dieser Befehl erwartet ebenfalls wieder die Variable mit dem
zugewiesenen Dateihandle sowie eine Variable, die den String aufnehmen soll. Optional kann eine
Maximallnge angegeben werden, ansonsten verwendet NSIS 1.024 Zeichen als Maximum.
"FileRead" liest solange Daten, bis entweder das Zeilenende erreicht ist, bzw. bis ein Nullbyte
gelesen oder das Dateiende erreicht wurde. Aus dem Grund bentigen wir eine Endlosschleife, bis
ein leerer String als Ergebnis zurckgeliefert wird
Loop:
FileRead $0 $R0 1024
StrCmp $R0 "" EndLoop
Fr den Fall, dass ein Leerstring das Ergebnis ist, wird die Marke "EndLoop" angesprungen.
Andernfalls lassen wir uns den ausgelesenen String anzeigen und springen zurck zu "Loop"
DetailPrint "$R0"
goto Loop
EndLoop:

48

Nullsoft Scriptable Install System

Dateien suchen
Weil es zum vorigen Kapitel passt, soll das Suchen von Dateien nicht vergessen werden. Allerdings
ist es mit den Bordmitteln von NSIS nicht mglich, eine rekursive Suche zu gestalten, die sich ber
mehrere Ordner erstreckt. Dennoch willen ich mit einem einfachen Beispiel zeigen, wie man sich
den Inhalt des "Programme"-Ordners anzeigen lassen kann.
Dazu bentigen wir zunchst die Funktion "FindFirst", der wir zuerst eine Variable fr die Suche
bergeben mssen - sozusagen das, was Sie von diversen Programmiersprachen als
Rckgabewert der (meist) gleichnamigen Funktion kennen. Der zweite Parameter ist eine Variable,
die den zuerst gefundenen Datei- oder Ordnernamen enthalten wird. Und in der letzten Variablen
geben Sie den oder die Dateitypen an, nach denen Sie suchen,
FindFirst $R0 $R1 "*.*"
In Delphi wrde das dem Aufruf
r0 := FindFirst('*.*',faAnyFile,r1);
entsprechen. Zu beachten ist dabei selbstverstndlich, dass "r1" hier weit mehr als nur
den Datei- oder Ordnernamen enthlt. Aber solche Feinheiten sind mit NSIS leider nicht
mglich.
Es ist nun wichtig, das Ergebnis der ersten Variablen auszuwerten. Wurden keine Dateien
gefunden, dann enthlt die Variable nichts, und Sie knnen die Suche abbrechen. Wir tun dies,
indem wir die Marke "skipLoop" anspringen
StrCmp $R0 "" skipLoop
Ansonsten treten wir in die Schleife ein
Loop:
und berprfen den gefundenen Dateinamen. Enthlt er ebenfalls keinen Wert, dann wurde keine
Datei gefunden (bzw. keine weitere Datei), und wir beenden die Suche. Allerdings mssen wir in
dem Fall noch das Handle freigeben. Auch das ist Ihnen bekannt, wenn Sie schon mit Delphi oder
hnlichen Sprachen nach Dateien gesucht haben. Wir springen daher ein anderes Ziel an, in dem
dann das Handle freigegeben wird (dazu dann spter)
StrCmp $R1 "" endLoop
Sollte der gefundene Dateiname etwas enthalten, prfen wir, dass dies nicht "." oder ".." ist. Auch
das ist Ihnen vielleicht von Ihrer Programmiersprache bekannt. Der einzelne Punkt steht fr das
aktuelle Verzeichnis, die beiden Punkte symbolisieren das bergeordnete Verzeichnis. In dem Fall
bergehen wir die Anzeige des gefundenen Wertes mit relativen Sprngen
StrCmp $R1 "." +3
StrCmp $R1 ".." +2
Ansonsten interessiert uns der Datei- oder Ordnername, also zeigen wir ihn an
DetailPrint "gefunden: $\"$R1$\""
und suchen dann mit "FindNext" die nchste Datei und springen zurck
FindNext $R0 $R1
goto Loop

49

Nullsoft Scriptable Install System

Nehmen wir als Beispiel an, es wurde keine weitere Datei gefunden. Der Sprung zurck zum
Beginn der Schleife wrde nun dafr sorgen, dass der Inhalt von "$R1" berprft und als leer
festgestellt wird. Demzufolge wird die bereits oben erwhnte Bedingung wirksam, und das Setup
springt die Marke "endLoop" an. Hier geben wir das Handle der Suche frei, und das war es auch
schon
endLoop:
FindClose $R0
skipLoop:
Und das soll nicht rekursiv klappen?
Meiner Meinung nach Nein ... jedenfalls nicht mit den Mitteln von NSIS.
1. Zum einen besteht die Gefahr, dass der Stack berluft wenn man nicht genau aufpasst.
2. Auerdem bieten "FindFirst" und "FindNext" keine Unterscheidung, ob es sich bei
dem gefundenen Namen um den Namen einer Datei oder eines Ordners handelt. Das
bedeutet, Sie mssten auf Verdacht versuchen, den ermittelten Namen als Ordner zu
behandeln und dort hinein zu wechseln.
3. Und damit ergibt sich das dritte Problem: die einzige Mglichkeit, das Verzeichnis zu
wechseln, ist der Befehl "SetOutPath". Allerdings liefert er keinen Fehlercode zurck.
Sollte ein Fehler auftreten (weil entweder das Verzeichnis nicht existiert, bzw. weil es sich
evtl. um den Namen einer Datei handelt), dann wird versucht, den Ordner anzulegen. Und
wenn Sie hier nicht aufgepasst haben und das aktuelle Arbeitsverzeichnis des Setup immer
noch mit dem ursprnglichen Zielpfad identisch ist, dann erzeugen Sie u.U. eine Menge
leerer Ordner, die alle nach irgendwelchen Dateien benannt sind.
Die beste Mglichkeit fr eine rekursive Dateisuche ist deshalb meiner Ansicht nach ein externes
Plugin - geschrieben in Delphi, C oder einer anderen Programmiersprache.
Dank der Erweiterbarkeit von NSIS lsst sich so ein Plugin leichter einbinden und schneller nutzen,
als umstndlich Code fr eine rekursive Dateisuche zu entwerfen.

50

Nullsoft Scriptable Install System

Ereignisse des Installers


Es gibt ein paar Ereignisse des Installers, die Sie "abfangen" und zum Bearbeiten Ihres Codes verwenden knnen.
Name
.onGUIInit
.onInit
.onInstFailed
.onInstSuccess

Bedeutung
Wird aufgerufen, bevor die erste Seite des Setup erscheint.
Wird beim Start des Setup aufgerufen.
Wird aufgerufen, wenn der Benutzer die Installation auf Grund
eines Fehlers abbricht.
Wird vor dem Beenden einer erfolgreich verlaufenen Installation
aufgerufen.

Daneben gibt es auch Ereignisse, die speziell fr den Deinstaller gedacht sind und mit dem Prfix
"un." beginnen, beispielsweise
Name
un.onInit

Bedeutung
Wird beim Start des Deinstallers aufgerufen

Weitere finden Sie in der Dokumentation zu NSIS.


Dieses Prinzip halte ich persnlich fr etwas unglcklich. Es dient zwar der sauberen Trennung von
Setup und Deinstaller, allerdings wirkt sich das auch auf eigene Funktionen aus. So akzeptiert
nmlich der Deinstaller nur den Aufruf von Funktionen, die mit dem Prfix "un." beginnen.
Mchten Sie also hufig bentigte Routinen in eigene Funktionen auslagern, sind Sie
mglicherweise gezwungen, zwei Versionen der gleichen Funktion zu schreiben: eine fr die
Installation, eine zweite fr die Deinstallation.
Wenn Sie ein Ereignis benutzen wollen, um bestimmten Code auszufhren, dann schreiben Sie
eine entsprechende Funktion und fllen Sie sie mit dem gewnschten Code, beispielsweise
Function .onInit
MessageBox MB_OK \
"Die Installation wird dieser Software startet jetzt."
; ggf. weiterer Code
FunctionEnd

51

Nullsoft Scriptable Install System

Headerdateien
hnlich den Headerdateien von C oder Units von Delphi knnen Sie Definitionen und hufig
benutzte Funktionen auslagern. NSIS-Headerdateien tragen die Endung ".nsh" und werden mit der
"!include"-Anweisung zweckmigerweise am Anfang des Skriptes eingebunden
!include "meine_headerdatei.nsh"
Das Format der Headerdatei entspricht dabei dem Skriptformat.

Makros
Bei Makros handelt es sich um eine Abfolge von Befehlen, die sich innerhalb eines Skripts
befinden. Im Gegensatz zu Funktionen mssen Makros immer vor der Funktion geschrieben
werden, in der sie aufgerufen werden sollen. Das folgende Beispiel wre falsch und wrde einen
Fehler verursachen
Function .onInit
!insertmacro Test
FunctionEnd
!macro Test
MessageBox MB_OK "Hallo, Welt!"
!macroend
Richtig wre, das Makro vor der Funktion zu deklarieren. Makros sind hilfreich, wenn man
identische Befehlsfolgen mehr als einmal bentigt. Und im Gegensatz zu Funktionen kann das
Makro sowohl fr den Installer als auch fr den Deinstaller aufgerufen werden.
Sie mssen allerdings beachten, dass Makros wie Includedateien eingebunden werden. Das
bedeutet, aus dem obigen Beispiel wird folgendes
Function .onInit
MessageBox MB_OK "Hallo, Welt!"
FunctionEnd
Sprungmarken drfen deshalb auch nur relativ sein. Namentliche Sprungmarken knnen Sie nicht
verwenden, wenn Sie das Makro mehrfach verwenden wollen. Der Compiler wrde bemngeln,
dass die Marke bereits dekariert wurde. Das folgende Beispiel liee sich nur einmal verwenden
!macro Link
DetailPrint "springe ..."
goto m.done
DetailPrint "... dieser Text ist nicht zu sehen"
m.done:
DetailPrint "... angekommen"
!macroend
Wrden Sie versuchen, dass Makro ein weiteres Mal einzubinden, dann wrden Sie vom Compiler
die Fehlermeldung erhalten, dass die Sprungmarke "m.done" bereits deklariert ist. Wie gesagt, das
hngt damit zusammen, dass das Makro direkt eingebunden wird und daher nicht wie eine
Funktion ber eigene lokale Variablen und Sprungmarken verfgen kann.

52

Nullsoft Scriptable Install System

Wenn Sie Makros berspringen wollen, mssen Sie daran denken, dass diese ja lokal eingebunden
werden. Besteht Ihr Makro beispielsweise aus 5 Zeilen, dann werden diese 5 Zeilen beim
Kompilieren des Skripts an der Stelle eingebunden, an der Sie das Makro aufgerufen haben.
Relative Sprnge mssen das demzufolge bercksichtigen. Im folgenden falschen Beispiel wird
versucht, das Makro zu berspringen
!macro WrongJump
DetailPrint "Makrozeile
DetailPrint "Makrozeile
DetailPrint "Makrozeile
DetailPrint "Makrozeile
DetailPrint "Makrozeile
!macroend

1"
2"
3"
4"
5"

Function .onInit
DetailPrint "versuche das Makro zu berspringen"
goto +2
!insertmacro WrongJump
DetailPrint ""
FunctionEnd
Wenn Sie das Beispiel ausprobieren, werden Sie allerdings feststellen, dass die Makrozeilen
trotzdem angezeigt werden - abgesehen von der ersten, die durch das "goto +2" tatschlich
bersprungen wird.
Zweckmig wre daher, Sprungmarken nach dem Makro zu deklarieren, die Sie als Ziel benutzen.
Das folgende korrekte Beispiel zeigt es Ihnen
Function .onInit
DetailPrint "so geht es richtig:"
goto NoMacro
!insertmacro WrongJump
NoMacro:
DetailPrint ""
FunctionEnd

53

Nullsoft Scriptable Install System

Mehrsprachige Setups
NSIS untersttzt von Haus aus mehrsprachige Setups. Fr die Sprachauswahl wird das LangDllPlugin bentigt, das einen entsprechenden Dialog zur Verfgung stellt. Dieses Plugin lsst sich am
besten im ".onInit"-Ereignis des Installers aufrufen. Dazu ist aber ein wenig Vorarbeit ntig.
Zunchst mssen die gewnschten Sprachen geladen werden, die Sie im Setup anbieten wollen,
Push
Push
Push
Push
Push

""
${LANG_GERMAN}
"Deutsch"
${LANG_ENGLISH}
"English"

usw. Dann knnen Sie den Dialog aufrufen, wobei Sie einen Titelleisten- und Dialogtext angeben.
Den sollten Sie etwa in Englisch whlen,
LangDll::LangDialog "Installer language" \
"Please select the language of the installer"
Der Rckgabewert entspricht einer Sprach-ID oder "cancel" (wenn der Anwender die
Sprachauswahl abgebrochen hat)
Pop $LANGUAGE
StrCmp $LANGUAGE "cancel" 0 +2
Abort
Nun reicht das allerdings immer noch nicht. Das Setup zeigt zwar die eingebauten Meldungen in
der ausgewhlten Sprache an, aber Ihre eigenen Definitionen (etwa die Komponenten und
Installationstypen) sind immer noch in der ursprnglichen Sprache.
Bei den Installer-spezifischen Einstellungen ("Name", "DirText", usw.) mssen Sie jetzt leider einen
so genannten "LangString" definieren. Bis zur Beta 3 war es noch mglich, sprachabhngige
Angaben zu treffen, beispielsweise
Name /LANG=${LANG_GERMAN} "INI-Cleaner fr LuckieDIPS"
Name /LANG=${LANG_ENGLISH} "INI-Cleaner for LuckieDIPS"
Dies wird vom Compiler inzwischen als Fehler bemngelt, weil "Name" nur noch einen Parameter
akzeptiert. Frher war es auch mglich, zuerst die gewnschte Sprachdatei zu laden und dann den
entsprechenden Text zuzuweisen, etwa
LoadLanguageFile "${NSISDIR}\...\German.nlf"
Name "INI-Cleaner fr LuckieDIPS"
LoadLanguageFile "${NSISDIR}\...\English.nlf"
Name "INI-Cleaner for LuckieDIPS"
Das funktioniert zwar noch, wird aber mit einer Warnung versehen, weil "Name" mehrfach definiert
wurde und damit (laut Compiler) Platz verschwendet.
Auf der sicheren Seite sind Sie daher momentan nur mit folgenden Zeilen
LangString AppName ${LANG_GERMAN} "INI-Cleaner fr LuckieDIPS"
LangString AppName ${LANG_ENGLISH} "INI-Cleaner for Luckie DIPS"
Name "$(AppName) 0.3"
Sie sehen hier brigens, dass solche Strings nicht wie Variablen in geschweiften, sondern in runden
Klammern bergeben werden.

54

Nullsoft Scriptable Install System

Das gilt auch fr die Namen der Sektionen. Um mehrsprachig zu arbeiten, mssen Sie auch hier
die Anweisung "LangString" benutzen und den Sektionsnamen in der jeweiligen Sprache
angeben, etwa
LangString Sec2Name ${LANG_GERMAN} "Desktop-Verknpfung"
LangString Sec2Name ${LANG_ENGLISH} "Desktop Shortcut"
Diesen String weisen Sie der gewnschten Sektion zu, und -voil- sie erscheint in Abhngigkeit der
vom Anwender gewhlten Sprache.
Section "$(Sec2Name)" AppLink
Wenn Sie solche Strings auch in der "Uninstall"-Sektion des Skriptes verwenden
wollen, mssen Sie (wie bei den Funktionen) das Prfix "un." davor setzen. Auch das ist
meiner Ansicht nach etwas umstndlich, weil Sie dadurch die gleichen Texte im
ungnstigsten Fall mehrfach definieren mssen.

So weit, so gut. Damit aber nun auch der Deinstaller die gewhlte Sprache verwendet, sollten Sie
Ihre Auswahl irgendwo speichern. Anbieten wrde sich beispielsweise der "Uninstall"-Schlssel
Ihrer Anwendung in der Registry, weil dort ohnehin relevante Informationen zum Entfernen der
Software hinterlegt werden.
Die Umsetzung ist auch nicht weiter kompliziert, Sie speichern den Wert der ausgewhlten Sprache
einfach nur als dword, was wie folgt aussehen kann
WriteRegDword HKLM "${UNINSTREGKEY}" \
"LangId" "$LANGUAGE"
Wenn der Anwender nun die Deinstallation startet, dann lesen Sie in der Funktion "un.onInit"
den gespeicherten Wert aus
ReadRegDword $LANGUAGE HKLM "${UNINSTREGKEY}" "LangId"
und damit erfolgt das Entfernen ebenfalls in der Sprache, die der Anwender eingangs gewhlt hat.
Ich verweise Sie an dieser Stelle auf Skript "icld.classic.ml.nsi", mit dem ein
deutsch- und englischsprachiges Setup fr den INI-Cleaner fr LuckieDIPS erzeugt
wird.

55

Nullsoft Scriptable Install System

Eigene Meldungen
Fr eigene Meldungen ist ein weiterer Schritt erforderlich. Das Setup prft ja beispielsweise, ob der
angemeldete Benutzer ber Administratorrechte verfgt und zeigt evtl. eine entsprechende
Meldung an. Diese Meldung ist natrlich jetzt auch zweisprachig zu gestalten
LangString AdminPriv ${LANG_GERMAN} \
"Zur Installation sind Administratorrechte erforderlich"
LangString AdminPriv ${LANG_ENGLISH} \
"This setup requires Administrator privileges"
Und statt des festen Textes geben Sie in der Dialogbox nun diesen String an
MessageBox MB_OK|MB_ICONEXCLAMATION "$(AdminPriv)"
Nun knnte man meinen, dass nach der Auswahl auch die Meldung in der gewhlten Sprache
angezeigt wird. Aber leider wird nach wie vor die zuerst definierte Sprache benutzt. Abhilfe schafft
das Auslagern der Prfroutinen und Meldungen in die Funktion ".onGuiInit" (bzw. in
"un.onGuiInit" fr den Deinstaller).
Warum das so ist, kann ich Ihnen leider nicht sagen. Fr die aktuelle Version 2.0 Beta 4 gilt
jedenfalls, dass die ausgewhlte Sprache bei eigenen Meldungen ignoriert wird, wenn diese in
".onInit" angezeigt werden. Dass die Anzeige der Meldung erst nach der Sprachauswahl
stattfindet, versteht sich sicher von selbst. Es funktioniert trotzdem nicht.

56

Nullsoft Scriptable Install System

Mehrsprachigkeit bei der modernen Oberflche


Das gleiche soll nun natrlich auch fr das moderne Aussehen des Setups gemacht werden. Die
Grundlagen entsprechen denen der klassischen Oberflche - Sie definieren verschiedene Strings
("LangString") fr die jeweiligen Sprachen.
Dann geben Sie die Sprachen, die das Setup untersttzen soll, in der von Ihnen gewnschten
Reihenfolge an, beispielsweise
!insertmacro MUI_LANGUAGE "English"
!insertmacro MUI_LANGUAGE "German"
Dieses Prinzip ist Ihnen ja bereits aus dem Kapitel "Spracheinstellungen" (s. Seite 21) bekannt. Und
dann rufen Sie in der Funktion ".onInit" ein entsprechendes Makro auf, mit dem der
Auswahldialog erscheint
!insertmacro MUI_LANGDLL_DISPLAY
Hier mssen Sie sich nicht darum kmmern, ob der Anwender die Sprachauswahl durchfhrt oder
abbricht. Das bernimmt das Makro fr sie und beendet das Setup ggf. Rein technisch funktioniert
das Setup bereits mit der gewnschten Sprache.
Beim Entfernen der Anwendung rufen Sie ebenfalls ein Makro auf, mit dem der Deinstaller die
zuvor ausgewhlte Sprache ermittelt
!insertmacro MUI_UNGETLANGUAGE
Dieses Makro macht im Prinzip nichts anderes als Sie bei der klassischen Oberflche. Es liest
einen entsprechenden Eintrag aus der Registry aus. Dazu bentigt es aber drei definierte Symbole,
die ihm sagen, wo sich der gesuchte Wert befindet
!define MUI_LANGDLL_REGISTRY_ROOT HKLM
!define MUI_LANGDLL_REGISTRY_KEY "${UNINSTREGKEY}"
!define MUI_LANGDLL_REGISTRY_VALUENAME "LangId"
Ich habe mich in dem Fall wieder fr den "Uninstall"-Schlssel in der Registry entschieden.
Kann der Wert nicht gefunden werden, zeigt auch der Deinstaller die Sprachauswahl an.
Allerdings mssen Sie noch ein Makro aufrufen, das die ausgewhlte Sprache auch speichert.
Idealerweise tun Sie das in der Sektion, in der Sie den Deinstaller anlegen
!insertmacro MUI_LANGDLL_SAVELANGUAGE
Der Unterschied zu dem Weg, den wir in der klassischen Oberflche gegangen sind, ist, dass die
Sprach-ID hier als String und nicht als dword gespeichert wird.

57

Nullsoft Scriptable Install System

Eigene Meldungen
Auch die moderne Oberflche hat das Problem, dass die Sprache von eigenen Meldungen ignoriert
wird, wenn diese (zusammen mit der Sprachauswahl) in der Funktion ".onInit" angezeigt
werden. Sie sollten daher auch hier Prfroutinen und Meldungen in die Funktion ".onGuiInit"
auslagern.
Das Problem dabei ist allerdings, dass diese Funktion durch die moderne Oberflche bereits
benutzt wird. Sie wird nmlich in der, hinter "MUI.nsh" stehenden "system.nsh" deklariert.
Demzufolge meldet der Compiler einen Fehler, wenn Sie versuchen, die Funktion in Ihrem Skript
erneut zu nutzen.
Die Lsung sind hier zwei Symbole (eins fr den Installer, das andere fr den Deinstaller), mit dem
Sie auf eigene Funktionen verweisen knnen.
!define MUI_CUSTOMFUNCTION_GUIINIT "guiInit"
!define MUI_CUSTOMFUNCTION_UNGUIINIT "un.guiInit"
In diesen Funktionen ("guiInit" und "un.guiInit") bringen Sie dann die Anzeige Ihrer eigenen
Meldungen unter, und das Setup bzw. der Deinstaller bercksichtigen nun auch hier die
ausgewhlte Sprache. Diese Symbole mssen vor den Seitenmakros (s. Seite 21) definiert werden.
Dem INI-Cleaner fr LuckieDIPS liegt mit dem Skript "icld.ml.nsi" ein Beispiel bei,
das ein deutsch- und englischsprachiges Setup mit der modernen Oberflche erzeugt.

58

Nullsoft Scriptable Install System

Aufgaben (= Tasks)
Wenn Sie die Dokumentation ber Inno Setup gelesen haben, wissen Sie bestimmt, dass es dort
so genannte Tasks (Aufgaben) gibt, die das Setup zustzlich ausfhren kann. Dazu gehren
beispielsweise Verknpfungen auf dem Desktop und hnliche Dinge, die im Ermessen des
Anwenders liegen.
Mit NSIS lassen sich solche Tasks auf hnliche Weise nachbilden, allerdings bentigen Sie dazu
eine externe INI-Datei und eine so genannte Custom Page (= benutzerdefinierte Seite) im Installer.
Das bedeutet, Sie bauen in die gewohnte Installationssequenz Ihre eigene Seite ein.
Die INI-Datei enthlt dabei die Anordnung der Elemente, die auf der Seite angezeigt werden sollen.
Im Fall der Aufgaben soll das ein Label mit erklrendem Text und zwei Checkboxen sein. Der Inhalt
der Datei sieht wie folgt aus
[Settings]
NumFields=3
[Field 1]
Type=label
Text=Erklrender Text
Left=0
Right=-1
Top=0
Bottom=20
[Field 2]
Type=checkbox
Text=Verknpfung im Startmen erzeugen
Left=0
Right=-1
Top=30
Bottom=40
State=1
[Field 3]
Type=checkbox
Text=Verknpfung auf dem Desktop erzeugen
Left=0
Right=-1
Top=45
Bottom=55
State=0
Die interessanten Teile habe ich rot markiert. So geben Sie unter "Type" den Typ des gewnschten
Elements an. Mglich sind u.a.

Name
Label
Checkbox
Radiobutton
FileRequest
DirRequest

Bedeutung
Static-Control zur Anzeige von Text
Checkbox zur Auswahl einer Option
Radiobutton zur Auswahl einer Option (nur jeweils eine mglich)
Auswahlmglichkeit fr Dateien
Auswahlmglichkeit fr Ordner

59

Nullsoft Scriptable Install System

Weitere finden Sie in der NSIS-Dokumentation unter dem Punkt "InstallOptions 2".

Diese INI-Datei binden Sie mit der Anweisung "ReserveFile" in Ihr Skript ein
ReserveFile "tasks.ini"
Dann mssen Sie angeben, wie diese neue Seite in der Installerlogik, oder besser gesagt
-reihenfolge auftauchen soll. Das heit, Sie fgen den neuen Befehl "Page" genau an der Stelle
ein, an der die neue Seite spter im Installationsablauf angezeigt werden soll. Ich habe mich dafr
entschieden, sie nach der Auswahl des Zielordners und unmittelbar vor der eigentlichen Installation
anzuzeigen
!insertmacro MUI_PAGE_DIRECTORY
Page custom TasksPage
!insertmacro MUI_PAGE_INSTFILES
Der rot markierte Name "TaskPage" ist dabei ein von Ihnen frei whlbarer Funktionsname. Das
heit natrlich auch, dass Sie eine solche Funktion schreiben mssen. Aber diese enthlt nur zwei
Makroaufrufe, mit denen Sie den Text fr den Installer festlegen und die eigentliche Seite anzeigen
lassen
Function TasksPage
!insertmacro MUI_HEADER_TEXT "Zustzliche Aufgaben" \
"Welche zustzlichen Aufgaben soll Setup ausfhren?"
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "tasks.ini"
FunctionEnd
Der Installer bernimmt hierbei die Anzeige der in der INI-Datei angegebenen Elemente. Damit die
Wahl des Anwenders dann auch bercksichtigt wird, mssen Sie in den Sektionen die Werte der
Controls abfragen. In diesem speziellen Fall sind es zwei Checkboxen, bei denen der Wert "State"
in der INI-Datei wichtig ist. Schauen Sie sich dazu bitte noch einmal die Beispieldatei auf der
vorigen Seite an. Der dort benutzte Wert Eins fr "State" bedeutet, dass die Checkbox bereits im
Vorfeld ausgewhlt ist. Und diesen Wert fragen Sie mit einem einfachen Makro in Ihrem Skript ab
!insertmacro MUI_INSTALLOPTIONS_READ $R0 \
"tasks.ini" \
; die INI-Datei
"Field 2" \
; die Sektion
"State"
; der gewnschte Eintrag
Wenn der Rckgabewert in der Variablen "$R0" Eins ist, dann ist die Checkbox ausgewhlt, und
Sie knnen die Verknpfung (oder was auch immer) erzeugen. Andernfalls berspringen Sie den
entsprechenden Code bitte einfach nur
StrCmp $R0 "1" 0 Done

60

Nullsoft Scriptable Install System

Werte an eigene Seiten bergeben


Als kleines Beispiel noch eine Abfrage von Benutzerdaten. Dazu fgen wir nach dem eben
gezeigten Prinzip eine weitere INI-Datei hinzu, die zwei Eingabefelder enthlt. Eins davon ist ein
Passwortfeld, bei dem die Eingabe durch Sternchen maskiert wird.
Diese Seite lassen wir gleich nach der Lizenz anzeigen und benutzen dazu die Funktion
"UserPage". Die Funktion enthlt vor der Anzeige der Seite noch zustzlichen Code, mit dem der
Name des angemeldeten Benutzers ermittelt werden kann
UserInfo::GetName
Pop $R0
Diesen ermittelten Namen bergeben wir mit Hilfe eines Makros an den "State"-Wert
!insertmacro MUI_INSTALLOPTIONS_WRITE "user.ini" \
"Field 2" "State" $R0
und dann sorgen wir, wie eben schon gezeigt, dafr, dass die neue Seite angezeigt wird
!insertmacro MUI_HEADER_TEXT "Benutzerinformationen" \
"Identifizieren Sie sich!"
!insertmacro MUI_INSTALLOPTIONS_DISPLAY "user.ini"
Sie knnen dieses Beispiel mit Hilfe der Dateien "tasks.nsi", "tasks.ini" und
"user.ini" nachvollziehen, die dieser Dokumentation beiliegen.

61

Nullsoft Scriptable Install System

Und was ist mit der klassischen GUI und eigenen Seiten?
Natrlich funktioniert das auch mit der Klassik-Oberflche. Dort stehen Ihnen allerdings nicht die
Makros der modernen Oberflche zur Verfgung. Das hat wiederum den Vorteil, dass Sie die
technischen Hintergrnde kennen lernen.
Doch zuerst einmal bernehmen Sie mit "ReserveFile" die gewnschten INI-Dateien in Ihr Skript.
Der erste Unterschied wird dann beim Entpacken der Dateien sichtbar. In der Funktion ".onInit"
schreiben Sie diesmal die folgenden Befehle
InitPluginsDir
File /oname=$PLUGINSDIR\user.ini user.ini
File /oname=$PLUGINSDIR\tasks.ini tasks.ini
Damit werden die beiden INI-Dateien in ein temporres Verzeichnis entpackt.
Als Beispiel wollen wir einen Blick in die Funktion "UserPage" werfen, weil wir hier den Namen des
angemeldeten Benutzers an die neue Seite bergeben mssen. Und hierbei offenbart sich dann
auch, dass es sich nur um das einfache Schreiben des Wertes in die INI-Datei handelt
WriteIniStr "$PLUGINSDIR\user.ini" "Field 2" "State" $R0
Unsere Seite wird dann mit Hilfe des InstallOptions-Plugins aufgerufen
InstallOptions::dialog $PLUGINSDIR\user.ini
Damit msste auch klar sein, dass das Auslesen der Werte spter auch ber einen INI-Befehl,
"ReadIniStr" um genau zu sein, erfolgt
ReadIniStr $R0 "$PLUGINSDIR\user.ini" "Field 2" "State"
ReadIniStr $R1 "$PLUGINSDIR\user.ini" "Field 3" "State"
MessageBox MB_OK "Hallo $R0$\nIhr geheimes Passwort war: $\"$R1$\""
Das, was in der modernen Oberflche das Makro getan hat, haben wir diesmal selbst gemacht.
Und so schwer war es ja auch nicht.
Es bleibt daher nur noch eine Aufgabe: hnlich wie in der modernen Oberflche mssen Sie
diesmal auch hier die Installerlogik (sprich: die Reihenfolge der Seiten) festlegen und Ihre eigenen
Seiten quasi einflechten. Und das geht relativ einfach
Page
Page
Page
Page
Page

license
custom UserPage
directory
custom TasksPage
instfiles

abhngig davon, welche Seiten Sie generell anzeigen wollen bzw. mssen. Fertig!
Dieses Beispiel knnen Sie mit den Dateien "tasks.classic.nsi", "user.ini" und
"tasks.ini" selbst ausprobieren.

62

Nullsoft Scriptable Install System

Seiten im Setup berspringen


Machen wir noch ein Praxisbeispiel, und nehmen wir an, Sie haben eine neue Softwareversion und
wollen diese ber eine bereits vorhandene Version kopieren. Dabei werden nur Dateien
berschrieben, so dass Sie sich nicht extra um eine Upgradefunktion (vgl. Seiten 35 und 76)
kmmern mssen.
Mit dem NSIS haben Sie verschiedene Mglichkeiten, den Pfad der bereits installierten Anwendung
zu ermitteln. Eine, schon angesprochene Variante wre "InstallDirRegKey", mit dem Sie den
Pfad anhand eines Wertes in der Registry ermitteln knnen. Nehmen wir an, dass sich der
Deinstaller im selben Ordner befindet, dann lautet die Anweisung einfach
InstallDirRegKey HKLM "${UNINSTPACKAGEKEY}" "UninstallString"
(unter der Voraussetzung, dass "${UNINSTPACKAGEKEY}" auf den entsprechenden Pfad zeigt).
Sie knnen aber auch beliebige andere Werte und Schlssel benutzen, sofern die bereits
installierte Anwendung dort den Pfad hinterlegt hat.
Eine andere Mglichkeit ist, den Pfad mit Hilfe der bereits angesprochenen Skriptfunktionen zu ermitteln. Auch dafr wird in den meisten Fllen ein Eintrag in der Registry bentigt, aber machbar ist
es in jedem Fall.
Lange Rede, kurzer Sinn: nachdem wir den Pfad ermittelt haben, knnten wir eigentlich auf die
Anzeige der Verzeichnisauswahl verzichten. Immerhin soll die neue Version ja in den ermittelten
Pfad der alten Version installiert werden.
Bei NSIS gibt es in solchen Fllen die Mglichkeit, eigene Funktionen zu definieren, die beim
Erzeugen oder Anzeigen bzw. Verlassen von Dialogseiten aufgerufen werden sollen. Dazu
bentigen wir die drei folgenden Symbole
MUI_PAGE_CUSTOMFUNCTION_PRE
MUI_PAGE_CUSTOMFUNCTION_SHOW
MUI_PAGE_CUSTOMFUNCTION_LEAVE
die jeweils vor der gewnschten Seite definiert werden mssen und den Namen einer eigenen
Funktion als Parameter bentigen. Da uns im genannten Beispiel nur die Prffunktion interessiert,
die vor der Anzeige der Verzeichnisauswahl aktiv werden soll, bentigen wir nur eins der Symbole
!define MUI_PAGE_CUSTOMFUNCTION_PRE "OnDirInit"
!insertmacro MUI_PAGE_DIRECTORY
"OnDirInit" ist dabei der Name unserer Funktion, in der wir die Anzeige der Verzeichnisauswahl
ggf. unterbinden wollen. Das Prinzip dafr ist wieder recht einfach. Wir prfen, ob im ermittelten
Zielverzeichnis eine bestimmte Datei vorhanden ist. Sie knnen auch eine andere Methode
verwenden, wichtig ist nur, dass Sie im Erfolgsfall (= Prfung erfolgreich!) die Funktion mit "Abort"
beenden. Dadurch wird nmlich verhindert, dass die Seite angezeigt wird. Wenn Sie die Funktion
stattdessen normal beenden, sehen Sie auch die Seite.
Das folgende Beispiel stammt aus dem CHM-Setup der Win32-API-Tutorials fr Delphi und prft,
ob die "base.chm" im Zielordner vorhanden ist. In dem Fall wird "Abort" aufgerufen, was zur
Folge hat, dass die komplette Verzeichnisauswahl bergangen wird
Function OnDirInit
IfFileExists "$INSTDIR\base.chm" 0 +2
Abort
63

Nullsoft Scriptable Install System

FunctionEnd

Und wie ist das bei der klassischen Oberflche?


In der klassischen Ansicht benutzen Sie den "Page"-Befehl und geben nach dem Namen der Seite
maximal drei Parameter an. Das Prinzip ist das gleiche wie eben gezeigt: es gibt eine Pre-, eine
Show- und eine Leave-Funktion.
Da wir nur die Pre-Funktion bentigen, reicht ein Parameter aus
Page directory "OnDirInit"
Wenn Sie nicht gerade spezielle Makros fr die moderne Oberflche nutzen, kann die Funktion
sogar mit der auf der vorigen Seite gezeigten identisch sein.
Vielleicht noch kurz zur Begriffserklrung von Pre, Show und Leave
Name
Pre
Show
Leave

Bedeutung
Wird vor dem Erzeugen der Seite ausgelst.
Wird vor nach dem Erzeugen und vor dem Anzeigen ausgelst.
Wird nach dem Verlassen der Seite ausgelst.

Bei eigenen Seiten (vgl. dazu auch Seite 62) stehen Ihnen lediglich die Pre- (hier Creator genannt)
und die Leave-Funktion zur Verfgung. Der dritte Parameter wre der Titel der Seite.
Beispielsweise
Page custom OnTasksInit OnTasksLeave ":Zustzliche Aufgaben"
Der Doppelpunkt ist dabei wichtig, da der von Ihnen benutzte Titel lediglich an den bereits
vorhandenen Fenstertitel angehangen wird.

64

Nullsoft Scriptable Install System

Kontakt mit dem Microsoft Installer


Sehr interessant finde ich die Fhigkeit von NSIS, mit Hilfe der System-DLL auf beliebige andere
DLLs zugreifen zu knnen. Ich habe das verwendet, um beispielsweise einen Hotfix fr ein anderes
Produkt installieren zu knnen.
Aber von vorn.
1. Ich habe ein paar kleine Programme unter dem Namen Windows Tools verffentlicht. Das
geschah mit Hilfe des Microsoft Installers. Wenn Sie die entsprechende Dokumentation
ber den MSI kennen, dann wissen Sie ja, dass ich sehr gern damit arbeite, weil er
beispielsweise die Nachinstallation von fehlenden Komponenten erlaubt, usw.
2. Dazu gab es einen Patch, der ebenfalls die Technik des Microsoft Installers benutzt.
Krzlich ist mir jedoch ein recht schwerwiegendes Problem in einem der Programme aufgefallen.
Ich wollte deswegen aber keinen weiteren MSP-Patch erstellen, sondern ich wollte das aktualisierte
Tool mit NSIS verffentlichen. Unter anderem auch deswegen, weil ich wusste, dass ich auf die
Funktionen des MSI zugreifen kann.
Die Aufgaben dieses Updates lassen sich dabei recht schnell zusammenfassen

Zuerst muss ermittelt werden, ob das Originalprogramm vorhanden ist, und wo es sich befindet. Im Fehlerfall ist das Setup abzubrechen.
Dann muss die Versionsnummer des Programms ermittelt und mit zwei gespeicherten Angaben verglichen werden.
o Wenn der Installer feststellt, dass es sich um das ursprnglich verffentlichte
Original handelt, muss er die Installation abbrechen, weil der Anwender zuerst den
offiziellen Patch einspielen soll.
o Wenn er feststellt, dass die Versionsnummer mit der des Updates identisch ist,
muss er das Setup ebenfalls abbrechen, da die Datei bereits aktualisiert wurde.
Das tatschlich verffentlichte Update funktioniert allerdings anders - auf Grund einiger
Kritik. So ist es mglich, das aktualisierte Programm auch zu installieren, wenn Produkt
und Patch nicht gefunden wurden. Das ist fr den Fall, dass jemand das Produkt zwar
installiert hatte, mittlerweile aber nur noch das Programm allein (stand-alone) ohne
Installation verwendet.

Das Originalprogramm suchen


An erster Stelle steht ein Blick auf die Funktionen, die wir verwenden wollen. In dem Fall ist es zum
Glck nur eine namens "MsiLocateComponent". Die Deklaration dieser Funktion zeige ich Ihnen,
die genaue Bedeutung der einzelnen Parameter schlagen Sie bitte in Microsoft Platform SDK oder
MSDN nach.
INSTALLSTATE MsiLocateComponent(
LPCTSTR szComponent,
LPTSTR lpPathBuf,
DWORD* pcchBuf
);
65

Nullsoft Scriptable Install System

Der erste Parameter bezeichnet die so genannte ComponentId, mit der die Komponente eindeutig
identifiziert wird. Die gleiche ID darf es in der selben MSI-Installation kein zweites Mal geben! Der
Einfachheit halber ich sie am Anfang des Skriptes deklariert
!DEFINE UISCOMPONENT "{11F95563-1BE6-11D7-BD2C-F5BB11EB7543}"
Die benutzte ComponentId muss dem gesuchten Programm entsprechen. Wenn Sie
selbst MSI-Installation erstellen, dann sollten Sie die erforderliche ID kennen. Mehr zum
Thema MSI finden Sie in der entsprechenden Dokumentation.

Der zweite Parameter ist ein Zeiger auf einen Textpuffer, der spter den Pfad und Dateinamen der
gesuchten Komponente enthalten wird. Der letzte Parameter gehrt unmittelbar dazu, denn er gibt
die Gre des Puffers an und muss vorher entsprechend belegt werden.
In der oben gezeigten Form lsst sich die Funktion leider nicht aufrufen. Bei NSIS benutzen wir eine
DLL, die quasi die Verbindung herstellt, dafr aber auch eine eigene Syntax erwartet. In der
Dokumentation (im Anhang C) finden Sie eine kurze Einfhrung zu diesem Thema.
Zusammenfassend kann man sagen, dass Strings durch ein kleines t, Integer aller Art durch ein
kleines i und Zeiger durch ein Sternchen reprsentiert werden. In der Syntax von NSIS, bzw. der
genannten Plugin-DLL, wrde die obige Funktion daher wie folgt aussehen
MsiLocateComponentA(t, t, t, *i) i
Eine Funktion "MsiLocateComponent" gibt es eigentlich nicht. Sie wird nur in
Headerdateien oder Units verwendet und verweist in den meisten Fllen auf die AnsiVersion. Daneben gibt es noch eine Unicode-Variante derselben Funktion. Tatschlich
exportiert
auch
die
"msi.dll"
nur
diese
beiden
Varianten,
nmlich
"MsiLocateComponentA" (Ansi) und "MsiLocateComponentW" (Unicode).
Aus dem Grund mssen wir die Ansi-Version direkt aufrufen.
Das reicht aber noch nicht ganz, denn es fehlt noch die Zuordnung der Variablen, die wir abfragen
wollen. Dazu muss man wissen, dass die internen NSIS-Variablen ($0-$9, $R0-$R9)
entsprechend gemappt (r0-r9, r10-r19) werden. Das bedeutet, wenn wir die Variable "r0"
benutzen, finden wir das Ergebnis spter in "$0", und umgekehrt.
In der o.g. MSI-Funktion interessieren uns aber lediglich der Textpuffer, der den Pfad und
Dateinamen enthalten soll, die Gre und der Rckgabewert. Die ComponentId mssen wir
natrlich auch benutzen, aber hier bergeben wir einen festen Wert, der sich nicht ndert.
Auerdem, das wurde ja bereits gesagt, muss ein entsprechender Speicher reserviert werden. Das
bernimmt glcklicherweise die System-Plugin-DLL fr uns, aber wir mssen angeben, wie viel
Speicher reserviert werden soll.
Wir weisen darum der NSIS-Variablen "$1" den Wert von "NSIS_MAX_STRLEN" (1024) zu
StrCpy $1 ${NSIS_MAX_STRLEN}
Nun knnen wir die Funktion aufrufen
System::Call "msi::MsiLocateComponentA(t '${UISCOMPONENT}', \
t .r0, *i r1) i.r2"
66

Nullsoft Scriptable Install System

Wie ich bereits schrieb, sind die rot markierten Variablen die gemappten Entsprechungen von
NSIS-Variablen. "r1" beispielsweise steht fr "$1", der wir gerade den Wert 1024 zugewiesen
haben. "r0" ($0) wird den Dateinamen enthalten, "r2" ($2) das Ergebnis der Funktion.
Die Punkte vor "r0" und "r2" sind brigens Pflicht, wenn Sie die Ergebnisse spter auswerten
wollen. Obwohl "r1" als Zeiger auf einen DWORD-Wert normalerweise auch auswertbar wre, wird
hier kein Punkt gesetzt, weil es sich um einen Zeiger handelt.
Als erstes berprfen wir nun das Ergebnis der Funktion - zu finden in "r2" bzw. (NSIS-lokal) "$2".
Da es sich hier um eine MSI-Funktion handelt, mssen wir auch die MSI-Rckgabewerte beachten.
Wichtig ist hier die so genannte INSTALLSTATE_LOCALE-Konstante, die den numerischen Wert 3
hat. Wenn Sie dieses Ergebnis erhalten, bedeutet das, das gesuchte Programm ist installiert. Jeder
andere Wert wird von uns als Fehler interpretiert.
StrCmp $2 "3" +3
er wird also der Inhalt der NSIS-Variablen mit dem Wert 3 verglichen. Ist das Ergebnis positiv,
werden die nchsten zwei Zeilen im Skript bersprungen. Dabei handelt es sich um die
Fehlermeldung, dass die gesuchte Komponente nicht gefunden wurde, und den Abbruchbefehl.
Wenn wir aber das gewnschte Ergebnis erhalten, dann sollte sich in "$0" nun der Pfad und Dateiname der gesuchten Komponente befinden. Das knnen wir recht simpel mit einer Dialogbox
prfen
MessageBox MB_OK "$0"

67

Nullsoft Scriptable Install System

Die Versionsnummer von Programmen ermitteln


NSIS enthlt praktischerweise eine Funktion zum Ermitteln von Versionsnummern. Obwohl diese
Funktion "GetDllVersion" heit, lsst sie sich auch fr EXE-Dateien verwenden. Die Funktion
erwartet neben dem Dateinamen zwei Parameter, die jeweils das hherwertige und niederwertige
Word der Versionsnummer enthalten
GetDllVersion "$0" $R0 $R1
Die Dokumentation von NSIS enthlt ebenfalls ein Beispiel, wie man diese zwei Werte in eine
lesbare Version im Format "x.x.x.x" umwandeln kann. Sie finden diese Funktion im Kapitel 4, in
der Hilfe zu "GetDllVersion".
Der Vergleich mit den gespeicherten Versionsnummern ist dann wieder recht einfach. Ich habe in
meinem Skript am Anfang die beiden mglichen Versionen deklariert
!DEFINE VER "1.0.0.172"
!DEFINE UNPATCHEDVER "1.0.0.135"
Wird beim Vergleich festgestellt, dass es sich um die Originalversion ($UNPATCHEDVER) handelt,
dann beendet sich das Skript mit einer entsprechenden Meldung. Wie gesagt, der Benutzer sollte in
diesem Fall erst den offiziellen Patch einspielen
StrCmp "$R2.$R3.$R4.$R5" "${UNPATCHEDVER}" 0 +3
MessageBox MB_OK|MB_ICONEXCLAMATION \
"Die Version ${UNPATCHEDVER} von ${NAME} \
kann mit diesem ${SETUP} nicht aktualisiert werden."
Abort
Wird festgestellt, dass die Versionsnummer dem Hotfix entspricht, wird das Setup ebenfalls
beendet, weil die Datei in dem Fall ja bereits aktualisiert wurde
StrCmp "$R2.$R3.$R4.$R5" "${VER}" 0 +3
MessageBox MB_OK|MB_ICONEXCLAMATION \
"${NAME} wurde bereits mit diesem ${SETUP} aktualisiert."
Abort
Nichts wirklich Unbekanntes also.

68

Nullsoft Scriptable Install System

Die Alternative - das Produkt bzw. den Patch aufspren


Wenn Sie wirklich sichergehen wollen, dass ein MSI-basiertes Produkt wirklich installiert ist, bzw.
dass ein bestimmter Patch wirklich eingespielt ist, knnen Sie zwei weitere MSI-Funktionen nutzen,
die prinzipiell dieselben Parameter nutzen
UINT MsiGetProductInfo(
LPCTSTR szProduct,
LPCTSTR szProperty,
LPTSTR lpValueBuf,
DWORD* pcchValueBuf
);

UINT MsiGetPatchInfo(
LPCTSTR szPatch,
LPCTSTR szAttribute,
LPTSTR lpValueBuf,
DWORD* pcchValueBuf
);

Der Unterschied ist, dass Sie bei "MsiGetProductInfoA" den Produktcode der Anwendung
angeben, whrend es sich bei "MsiGetPatchInfoA" um den Packagecode des Patches handelt.
Beide Angaben erhalten Sie notfalls von demjenigen, der die MSI-Installation und den MSP-Patch
erstellt hat. Wenn Sie das sind, umso besser ... J
Vom Prinzip her ndert sich nichts. Wir weisen wie gehabt 1.024 Zeichen fr den Textpuffer zu
StrCpy $1 ${NSIS_MAX_STRLEN}
rufen die Funktion mit den entsprechenden Angaben auf
System::Call "msi::MsiGetProductInfoA( \
t '{61CA5C40-0CEF-11D6-931D-00001C01A8CB}', \
t 'VersionString', \
t .r0, *i r1) i.r2"
und lassen uns das Ergebnis in der Form Versionsnummer, Puffergre, Funktionsergebnis
anzeigen
MessageBox MB_OK "$0 -> $1 -> $2"
Der benutzte Attributwert "VersionString" ist ein MSI-bezogener Wert und bezieht sich
auf die im System hinterlegte Versionsnummer der installierten Anwendung. Andere und
die Erklrungen dazu finden Sie in der Hilfe zum Microsoft Installer (s. MSDN oder
PSDK).
Sollten Sie diese Anwendung zuflligerweise
auf Ihrem Rechner installiert haben, dann
mssten Sie jetzt folgendes sehen
Der Rckgabewert Null entspricht dabei
ERROR_SUCCESS, was ein gutes Zeichen
ist.
Erhalten Sie stattdessen den Wert "1605", dann entspricht das dem MSI-Fehler
ERROR_UNKNOWN_PRODUCT, was Sie als Indiz dafr nehmen knnen, dass die gesuchte
Anwendung nicht vorhanden ist. In dem Fall sollten Sie das Setup abbrechen.

69

Nullsoft Scriptable Install System

Bei MSP-Patches gelten die gleichen Rckgabewerte. Allerdings haben Sie hier nur die
Mglichkeit, den Namen der lokalen Datei in Erfahrung zu bringen (Attribut = "LocalPackage").
Dass der Patch lokal gesichert wird, hat mit der Funktionsweise des MSI zu tun.
Der Aufruf ist, wie gesagt, identisch. Sie
bergeben die ID des Patches und das
Attribut, sowie Textpuffer und Gre.
Und wenn der Patch vorhanden ist, sollten Sie
eine Ausgabe wie in dem nebenstehenden
Bild sehen. Der Name wird bei Ihnen
mglicherweise ein anderer sein, aber das
Ergebnis sollte so aussehen.
StrCpy $1 ${NSIS_MAX_STRLEN}
System::Call "msi::MsiGetPatchInfoA( \
t '{71E4F420-6D8F-11D7-BD2C-985991BCB043}', \
t 'LocalPackage', \
t .r0, *i r1) i.r2"
MessageBox MB_OK "$0 -> $1 -> $2"

70

Nullsoft Scriptable Install System

MSI-Setups deinstallieren und blockieren


An dieser Stelle mchte ich demonstrieren, wie man eine vorhandene MSI-Installation entfernen
kann. Warum soll das notwendig sein?
Stellvertretend mchte ich als Beispiel die Win32-API-Tutorials anfhren. Von Version 1.5 bis 1.7
wurden diese als MSI-Installation ausgeliefert. Mit der Version 1.8 erfolgte die Auftrennung in
einzelne Pakete, von denen die Hilfedateien und die Beispielprogramme mit einem NSIS-Setup
ausgerstet wurden.
Diese neuen Setups sind in der Lage, alle bekannten MSI-Versionen der Tutorials zu erkennen und
zu entfernen. Dazu erforderlich ist lediglich der Produktcode der jeweiligen Version. Zur
Anschauung soll der Produktcode der Version 1.7 dienen
!define TUT17 "{9E172AA4-F17E-11D6-BD2C-849DB2B3AF42}"
Im Setup benutze ich nun die MSI-Funktion "MsiQueryProductState", um zu ermitteln, ob das
Produkt berhaupt installiert ist. Die Funktion erwartet lediglich den o.g. Code und liefert als
Ergebnis einen so genannten Installationsstatus zurck. Wenn dieser Wert 5 (=
INSTALLSTATE_DEFAULT) ist, dann knnen wir davon ausgehen, dass das Produkt installiert ist
System::Call "msi::MsiQueryProductStateA(t '${TUT17}') i.r0"
StrCmp $0 "${INSTALLSTATE_DEFAULT}" 0 +3
Ist das der Fall, dann wird der Produktcode auf dem Stack abgelegt und danach eine spezielle
Funktion aufgerufen, mit der die MSI-Version entfernt werden soll
Push "${TUT17}"
call CallMsiDeinstaller
In dieser Funktion muss der Produktcode natrlich zuerst vom Stack geholt werden. Auerdem
wird der Benutzer darber informiert, dass eine ltere Version gefunden wurde, die entfernt werden
muss. Wenn der Benutzer dies nicht wnscht, dann wird das Setup der neuen Version
abgebrochen.
Wir gehen davon aus, dass der Benutzer die alte Version entfernen mchte. Und dazu bentigen
wir dann die Funktion "MsiConfigureProduct"
UINT MsiConfigureProduct(
LPCTSTR szProduct,
int iInstallLevel,
INSTALLSTATE eInstallState
);
Auch diese Funktion bentigt natrlich den Produktcode, den wir bereits kennen. Der zweite
Parameter "iInstallLevel" gibt an, wie viel von dem Produkt installiert (oder in unserem Fall:
entfernt werden soll). Es gibt drei Konstanten, von denen uns "INSTALLLEVEL_MAXIMUM"
interessiert. Deren numerischer Wert ist 0xFFFF.
Der letzte Parameter gibt den Installationsstatus an. Auch hier gibt es verschiedene Konstanten,
wobei wir nur "INSTALLSTATE_ABSENT" (= 2) nutzen, weil wir damit das Produkt entfernen
knnen.
In der NSIS-Syntax sieht der Aufruf der Funktion daher wie folgt aus
System::Call "msi::MsiConfigureProductA(t '${TUT17}', i 0xFFFF,\
i 2) i.r0"
71

Nullsoft Scriptable Install System

Normalerweise erscheint nun das bekannte Fenster des Microsoft Installers, das Sie ber den
Status der Deinstallation informiert. Der Rckgabewert der Funktion ist Null, wenn die Deinstallation
erfolgreich war. In allen anderen Fllen erscheint im Fall der Tutorials eine Meldung, und das neue
Setup wird abgebrochen.
So weit, so gut. Nun hindert den Anwender aber niemand daran, die alte MSI-Version ein zweites
Mal zu installieren, nachdem die NSIS-Version installiert ist. Wie auch? Der NSIS benutzt eine
andere Technik, und der Microsoft Installer wird sicher nicht nach einer NSIS-Version suchen. J
Also mssen wir ran!
Zunchst ist es wichtig, den Upgrademechanismus des Microsoft Installers herauszufinden. Wir
gehen davon aus, dass der Entwickler des MSI-Setup so clever war und einen solchen Schutz
eingebaut hat, damit sich keine lteren MSI-Versionen ber neuere MSI-Versionen installieren
lassen.
Bei einem MSI-Test wurde ich unter "HKCU\Software\Microsoft\Installer\Products"
fndig. Das heit, ich habe zunchst einfach nur nach dem Namen der Installation gesucht, denn
die benutzten Codes sahen anfangs doch sehr merkwrdig aus.
Ich habe Ihnen auf der vorigen Seite den Produktcode der Version 1.7 der Win32-API-Tutorials
gezeigt. Wie sich herausstellte, wurden die Zeichen der ersten drei Felder komplett vertauscht, das
bedeutet: von hinten nach vorn geschrieben, und die beiden letzten Felder wurden byteweise
vertauscht. Aus dem Produktcode wurde deshalb die Zahlenkolonne
4AA271E9E71F6D11DBC248D92B3BFA24
In diesem Schlssel fand sich u.a. die aktuelle Versionsnummer im Format 0x01070000.
So einen Schlssel mssen wir nun auch erzeugen. Zu beachten ist dabei allerdings, dass ein
bereits benutzter Produktcode nicht noch einmal benutzt werden darf. Das heit, Sie drfen keinen
Code nehmen, den Sie bereits in einer frheren MSI-Installation verwendet haben.
Das sollten Sie nur tun, wenn die MSI-Version keinen eingebauten Upgradeschutz hat.
Das heit, wenn der Entwickler des MSI-Setup versumt hat, auf bereits installierte
Version zu prfen. Wenn Sie nmlich einen bereits benutzten Produktcode verwenden,
dann erscheint beim Versuch, die MSI-Version erneut zu installieren, eine
Fehlermeldung. Unschn, aber im Ausnahmefall mglich.
Darum denken wir uns ganz einfach selbst eine GUID aus und entfernen die geschweiften
Klammern und die Bindestriche. Wenn Sie es bertreiben mchten, dann vertauschen Sie die
Zeichen in der Art, wie das der MSI tut. J
Ebenfalls wichtig ist aber auch der so genannte Upgradecode der MSI-Version. Dieser Code muss
innerhalb desselben Produktes immer identisch sein, denn nur dadurch sind ltere Versionen in der
Lage, neuere Versionen zu erkennen und die Installation zu verweigern. Das bedeutet, hier
bentigen Sie unbedingt den originalen Upgradecode der MSI-Version Ihrer Anwendung.
Allerdings liegt auch der nur in der o.g. vertauschten Schreibweise vor, so dass aus der GUID der
Tutorials die Zeichenkette "1853AD778D066D113B030000C1108ABC" wird.
Diese Angabe wird unter "HKCU\Software\Microsoft\Installer\UpgradeCodes"
gespeichert und enthlt lediglich den o.g. "verdrehten" Produktcode.
Was mssen wir also tun?
Wir erzeugen zunchst einen Schlssel mit einem neuen (fiktiven) Produktcode und tragen dort die
aktuelle Versionsnummer im, vom MSI benutzten Format ein. Dann erzeugen wir einen Schlssel
72

Nullsoft Scriptable Install System

mit dem originalen Upgradecode und tragen dort den neuen (fiktiven) Produktcode ein.

Und wie Sie sehen knnen, ist diese Aktion von Erfolg gekrnt, denn beim Versuch, eine der alten
MSI-Versionen der Tutorials zu installieren, erscheint die folgende Meldung

Natrlich mssen Sie beim Entfernen Ihrer Software dann auch diese MSI-Eintrge
wieder entfernen. Zur Ansicht liegt den Beispielen eine Headerdatei namens "disablemsi.nsh" bei, die die notwendigen Makros fr die o.g. Eintrge enthlt. Die Datei ist
ausfhrlich kommentiert.
Soviel zur Kontaktaufnahme mit dem Microsoft Installer.
Und was mit der "msi.dll" geht, funktioniert prinzipiell auch mit anderen DLLs.

73

Nullsoft Scriptable Install System

Alte NSIS-Anwendungen entfernen


Der Grund, warum ich diesem Thema ein eigenes Kapitel widme, liegt in der Technik, die der NSIS
zur Deinstallation verwendet.
Wie geht man blicherweise vor? Wenn man in der Registry einen Schlssel findet, der auf eine
bereits installierte Version hindeutet, dann wird man den entsprechenden "UninstallString" der
installierten Anwendung auslesen, das darin vermerkte Programm starten und mit der Installation
der neuen Anwendung solange warten, bis die alte Version entfernt wurde.
Zwar bietet NSIS die notwendigen Funktionen an, allerdings funktioniert das bei ihm selbst nicht
ganz so einfach. Damit sich der Deinstaller whrend des Entfernens auch selbst lschen kann,
kopiert er sich selbst unter anderem Namen in den "Temp"-Ordner. Diese umbenannte Kopie startet
er, und dann beendet er sich.
Nun werden Sie auch wissen, warum das neue Setup nicht wirklich wartet. Richtig: Sie haben den
echten Deinstaller anhand des Eintrages in der Registry gestartet. Aber der hat die Kontrolle an
seine kopierte Version bergeben und sich dann beendet.
Fr Ihr Setup ist die Deinstallation damit abgeschlossen, obwohl das natrlich nicht zutrifft.
Darum mssen Sie selbst in den Prozess eingreifen, wenn Sie Erfolg haben wollen. Und weil NSIS
Open Source ist, kann man die Ansatzpunkte auch herausfinden wenn man will J
Der beste Weg ist eine eigene Funktion. Ich habe sie "CallNSISDeinstaller" genannt. Bevor
Sie sie aufrufen, legen Sie den Pfad- und Dateinamen des Deinstallers auf dem Stack ab. Die
Funktion holt sich den Namen vom Stack und zeigt dann erst einmal eine Meldung an, dass eine
ltere Version gefunden wurde
Function CallNSISDeinstaller
Pop $R0
MessageBox MB_YESNO|MB_ICONQUESTION \
"Es wurde eine ltere Version von ${PRODUCT} gefunden.\
Es wird empfohlen, diese Version zuerst zu deinstallieren.$\n$\n\
Soll Setup die Deinstallation der alten Version jetzt durchfhren?"\
IDNO BreakMe
Nun mssen Sie den gefundenen Deinstaller in den "Temp"-Ordner kopieren
CopyFiles /SILENT /FILESONLY $R0 $TEMP

74

Nullsoft Scriptable Install System

Jetzt knnen Sie aus dem Deinstaller den Pfad und den Dateinamen extrahieren. Den Pfad
brauchen wir, um dem kopierten Deinstaller sagen zu knnen, in welchem Verzeichnis sich die
installierte Anwendung befindet, und den Dateinamen bentigen wir zum Starten
Push $R0
call ExtractFilePath
Pop $R9
Push $R0
call ExtractFileName
Pop $R0
"ExtractFilePath" und "ExtractFileName" basieren auf einer Funktion, die Sie im
Anhang B der NSIS-Dokumentation finden (GetParent). Beide Funktionen liegen
auerdem in der Datei "utils.nsh" bei.

Der kopierte Datei starten wir jetzt mit "ExecWait" und bergeben den zuvor ermittelten Pfad, aus
dem wir den echten Deinstaller kopiert haben. Allerdings ist hier ein spezieller Parameter ntig,
damit das nochmalige Kopieren des Deinstallers verhindert wird.
ExecWait '"$TEMP\$R0$\" _?=$R9' $R1
In der Hoffnung, dass der Setup-Entwickler der alten Version daran gedacht hat, den Deinstaller
selbst auch zu lschen, prfen wir, ob eben jener noch vorhanden ist. Wenn Ja, dann mssen wir
von einem Problem bei der Deinstallation ausgehen und sollten das Setup dann beenden
IfFileExists "$R9\$R0" 0 Done
MessageBox MB_OK|MB_ICONEXCLAMATION \
"Fehler beim Entfernen des Produktes aufgetreten"
BreakMe:
Abort
Ansonsten kann unsere Funktion normal beendet, und die Installation der neuen Anwendung
fortgesetzt werden.

Der "Silent Mode"


Als Alternative (fr den Fall, dass Ihnen der eben beschriebene Weg zu aufwndig ist) knnen Sie
auch den eingebauten "Silent Mode" des Deinstallers probieren. Das heit, die Deinstallation findet
ohne Rckfragen statt. Dazu bergeben Sie dem Deinstaller den Parameter "/S".
Allerdings kommt hier wieder der schon erwhnte Nachteil zum Tragen: Sie starten den Deinstaller,
der sich kopiert, diese Kopie startet und sich dann beendet. Sie wissen also nicht wirklich, ob die
Entfernung der Software funktioniert hat.

75

Nullsoft Scriptable Install System

Idee fr eine Upgradefunktion


Ich habe ja bereits angekndigt, dass ich einen mglichen Ansatz fr eine Prffunktion vorstellen
mchte. Vielleicht kann man sagen, dass ich durch den Microsoft Installer ein wenig verwhnt bin.
Jedenfalls gefllt es mir nicht, wenn man verschiedene Programmversionen wild durcheinander
installieren kann.
Ergebnis meiner berlegungen ist die Headerdatei "version.nsh", die Sie in Ihr Skript einbinden
knnen. Die Headerdatei enthlt ein paar fertige Makros, auf die ich jetzt etwas nher eingehen
mchte.
Nachfolgend spielt es keine groe Rolle, in welchem Registryschlssel Sie die
notwendigen Versionsangaben speichern. Das liegt ganz in Ihrem Ermessen. Allerdings
sollten Sie Schlssel-namen vermeiden, die Versionsnummern enthalten.
Der Grund ist einfach der, dass jede von Ihnen verffentlichte Version die Informationen
einer evtl. bereits installierten Version finden muss. Wrde sich die Versionsnummer im
Schlsselnamen nun ndern, dann wre die Prffunktion wirkungslos, da sie nicht den
richtigen Schlssel finden kann.
Damit die vorgestellten Makros richtig funktionieren, wird nun eine vierstellige Versionsangabe
bentigt. Das bedeutet in dem Fall, dass vier Felder vorhanden sein mssen, die die Hauptversionsnummer, die Nebenversionsnummer, sowie die Release- und die Buildnummer enthalten,
bspw.
!define
!define
!define
!define

MAJOR "1"
MINOR "8"
RELEASE "0"
BUILD "0"

Die Versionsinformationen speichern


Beginnen wir mit dem logischen ersten Schritt: dem Speichern der Versionsinformationen. Dazu
benutzen wir das Makro "PRODUCT_WRITE_VERSIONINFO", das als Parameter den gewnschten
Schlssel in der Registry und die vier eben gezeigten Felder der Versionsnummer bentigt
!insertmacro PRODUCT_WRITE_VERSIONINFO HKLM "${UNINSTKEY}" \
${MAJOR} ${MINOR} ${RELEASE} ${BUILD}
Der Einfachheit halber habe ich in diesem Fall den "Uninstall"-Schlssel des Programms gewhlt.
Welchen Schlssel Sie whlen, hngt von Ihrem Produkt ab. Im Normalfall sollten Sie ebenfalls
einen Schlssel unter HKEY_LOCAL_MACHINE bevorzugen, weil dieser Schlssel von allen
Benutzern des Rechners abgefragt werden kann.
Besitzt ein Benutzer nicht die notwendigen Rechte, um in den HKLM-Schlssel zu schreiben, kann
Ihr Produkt aber dennoch installiert werden, dann sollten Sie einen Schlssel innerhalb von
HKEY_CURRENT_USER whlen.
Technisch gesehen passiert in dem gezeigten Makro folgendes: Die Haupt- und die
Nebenversionsnummer, sowie die Release- und die Buildnummer werden zu zwei so genannten
DWORD-Werte zusammengefasst. Aus der o.g. Beispielversionsnummer wrden so die beiden
Werte 0x00010008 und 0x00000000 werden.
Der beste Ort, das Makro aufzurufen, ist daher die Sektion, in der Sie auch den Deinstaller fr Ihr
Programm erzeugen.
76

Nullsoft Scriptable Install System

Die Versionsinformationen vergleichen


Der nchste logische Schritt wre nun der Vergleich. Das heit, der Anwender versucht, das Setup
ein zweites Mal zu starten. Oder es handelt sich sogar um eine ltere Version. Dieses Setup muss
nun die gespeicherten Informationen aus der Registry holen und mit seiner eigenen
Versionsnummer vergleichen.
Dazu dient das Makro "PRODUCT_COMPARE_VERSIONINFO", das wieder den Registryschlssel
und die aktuelle Versionsnummer des Setup bentigt
!insertmacro PRODUCT_COMPARE_VERSIONINFO HKLM "${UNINSTKEY}" \
${MAJOR} ${MINOR} ${RELEASE} ${BUILD}
Das Makro generiert aus den bergebenen Feldern ebenfalls zwei DWORDs und vergleicht sie mit
den in der Registry gespeicherten Daten. Sind die Werte identisch, dann erscheint eine
entsprechende Meldung, dass das Produkt bereits installiert ist und das Setup wird beendet.
Ist einer der in der Registry gespeicherten Werte hher als sein Gegenstck aus dem gestarteten
Setup, dann erscheint die Meldung, dass bereits eine aktuellere Version installiert ist. Und auch hier
wird das Setup natrlich beendet.
Die einzige Mglichkeit, das Setup auszufhren, besteht damit nur, wenn der in der Registry
gespeicherte Wert kleiner ist als der des Setup.
Die Versionsinformationen entfernen
Natrlich darf auch das Entfernen der Versionsangaben nicht fehlen. Wenn die Software komplett
deinstalliert wird, dann mssen auch die gespeicherten Angaben entfernt werden. Dazu dient das
Makro "PRODUCT_REMOVE_VERSIONINFO", das Sie am besten in der "Uninstall"-Sektion Ihres
Skriptes aufrufen,
!insertmacro PRODUCT_REMOVE_VERSIONINFO HKLM "${UNINSTKEY}"
Hier mssen Sie diesmal nur den Registryschlssel angeben. Die Versionsnummer Ihres Setup ist
nicht von Interesse, weil die Daten ohnehin aus der Registry entfernt werden.
Wenn der Registryschlssel nach dem Entfernen der Versionsangaben leer ist wird er ebenfalls
entfernt.
Hinweise
1. Wenn Sie diese Technik benutzen wollen, muss bereits Ihr allererstes Setup mit diesen
Makros ausgestattet werden. Halten Sie sich bitte das Prinzip noch einmal vor Augen: das
Setup startet und liest evtl. gespeicherte Informationen aus der Registry und vergleicht
diese mit seinen eigenen Angaben. Demzufolge muss also bereits Ihre allererste
verffentlichte Version diese Prfung eingebaut haben, auch wenn Sie zu dem Zeitpunkt
noch gar nicht wissen, ob es weitere Versionen geben wird.
Auch wenn Sie bereits Versionen ohne diesen Schutz verffentlicht haben, knnen Sie die
aktuelle Version Ihres Produktes damit ausstatten. Es besteht dann allerdings die Gefahr,
dass der Anwender eine der lteren Versionen noch hat und versucht, diese ber ihre neue
Version zu installieren.
Sie sollten in so einem Fall ber einen Wechsel der Registryschlssel usw. nachdenken.
Ich meine damit allerdings nicht den Schlssel der Versionsprfung, sondern allgemeine
Schlssel und Eintrge (etwa fr den Deinstaller und dergleichen). So verhindern Sie zwar
nicht die Installation der alten Version, aber zumindest werden notwendige Eintrge Ihrer
neuen Version nicht berschrieben.

77

Nullsoft Scriptable Install System

2. Wenn Sie eine Komponentenauswahl in Ihrem Programm benutzen, dann ist es vielleicht
strend, wenn sich das Setup nur ein einziges Mal ausfhren lsst. Mglicherweise mchte
der Anwender ein paar Komponenten zu einem spteren Zeitpunkt nachinstallieren.
Sorgen Sie in diesem Fall dafr, dass das Symbol SIMPLECHECK in der Headerdatei aktiv
ist, indem Sie in dieser Zeile
;!define SIMPLECHECK
das Semikolon entfernen. Dadurch wird der Abbruch bersprungen, wenn das Produkt
bereits mit der gleichen Version installiert ist.
Alternativ dazu knnen Sie das Symbol aber auch direkt in Ihrem eigentlichen Setupskript
definieren und so die Headerdatei unverndert lassen. Wichtig ist nur, dass der Symbol vor
dem Aufruf von "PRODUCT_COMPARE_VERSIONINFO" definiert wird.
Eine kleine Spielerei ...
Da ich in den vorigen Kapiteln schon ein paar ntzliche Dinge gezeigt habe, soll an dieser Stelle der
so genannte Wartungsmodus nicht fehlen. Sie kennen das evtl. vom Microsoft Installer. Wenn Sie
das Setup einer bereits installierten Anwendung starten, dann haben Sie die Mglichkeit, neue
Komponenten hinzufgen bzw. vorhandene Komponenten zu entfernen, usw.
Ich mchte diesen Wartungsmodus allerdings nur ansatzweise nachbilden. Es soll lediglich mglich
sein, die Installation ein weiteres Mal auszufhren, bzw. die bereits installierte Anwendung zu
entfernen.
Wenn Sie es wie beim MSI machen wollen, dann sollten Sie folgende Tipps beachten
1. Bei NSIS werden grundstzlich nur die Komponenten installiert, die Sie auswhlen. Bereits
vorhandene Komponenten werden jedoch durch die Abwahl des Hkchens nicht entfernt!
Sie verbleiben im Zielverzeichnis, da NSIS abgewhlte Sektionen bei der Installation
ignoriert.
Sie mssten daher eine unsichtbare Sektion erstellen, in der Sie prfen, welche anderen
Sektionen nicht ausgewhlt sind. Abhngig davon sind dann die dazu gehrenden Dateien
und Eintrge in der Registry oder in anderen Dateien zu entfernen.
2. Vor der Installation mssen Sie dann auch prfen, welche Komponenten bereits installiert
sind, damit Sie die entsprechenden Sektionen in der Auswahlliste aktivieren oder auch
deaktivieren knnen.
3. Und weil der MSI den Wartungsmodus auch anzeigt, wenn man den Eintrag in der
Systemsteuerung whlt, mssen Sie das Setup als "UninstallString" in die Registry
eintragen. Der Deinstaller sollte natrlich auch dort vermerkt werden, allerdings mit einem
anderen Namen, etwa "QuietUninstallString" o..
Wie gesagt, ich zeige lediglich, wie man die erneute Installation und das Entfernen der Anwendung
realisieren kann. Dazu bentigen wir natrlich zuerst wieder eine eigene Seite in der Installationslogik (s. dazu Seite 59).
Auerdem erforderlich sind zwei benutzerdefinierte Funktionen fr den Wartungsmodus. In der
ersten Funktion mssen wir prfen, ob die Versionsnummer des bereits installierten Produktes der
Versionsnummer des Setup entspricht. Ist das der Fall, kann der Dialog mit den Optionen
angezeigt werden.

78

Nullsoft Scriptable Install System

In der zweiten Funktion prfen wir, ob der Anwender als Option das Entfernen der bereits
installierten Version ausgewhlt hat. In diesem Fall ist das Setup nach der Deinstallation der alten
Version zu beenden.
Page custom MaintenancePre MaintenanceLeave
Die Funktion "MaintenancePre" erfllt die erste Aufgabe. Mit Hilfe eines weiteren Makros aus der
Headerdatei "PRODUCT_CHECK_VERSIONINFO" prfen wir die Versionsnummer der installierten
Anwendung und des Setup. Das Rckgabeergebnis ist dabei Null, wenn beide Versionen identisch
sind. Der Wert ist -1, wenn die installierte Version aktueller ist, und er ist 1, wenn das Setup
aktueller ist.
Uns interessiert daher nur der Rckgabewert Null, weil er besagt, dass die installierte Anwendung
mit der Version des Setup identisch ist. Andernfalls brechen wir die Anzeige des Wartungsmodus
mit "Abort" ab
!insertmacro PRODUCT_CHECK_VERSIONINFO HKLM "${UNINSTKEY}" ${MAJOR} \
${MINOR} ${RELEASE} ${BUILD} $R9
IntCmp $R9 0 +2 +2
Abort
Die Anzeige der Seite selbst sollte aus den vorigen Kapiteln bekannt sein (s. Seite 59), so dass ich
nicht mehr darauf eingehen mchte.
In der zweiten Funktion "MaintenanceLeave" wird dann lediglich ermittelt, ob der Anwender die
Deinstallation ausgewhlt hat. An sich ist das auch nicht neu, da lediglich ein Wert aus der eigenen
Seite abgefragt wird.
!insertmacro MUI_INSTALLOPTIONS_READ $R0 "maintenance.ini" \
"Field 3" "State"
Welcher Wert das genau ist hngt natrlich vom Umfang Ihrer Installationsseite ab. In
meinem Beispiel handelt es sich um den Eintrag "State" in der Sektion "[Field 3]".

Sie knnten an dieser Stelle prfen ob der Deinstaller vorhanden ist, ihn dann laden und ausfhren.
Dazu verweise ich Sie an das Kapitel auf Seite 74.
Zu beachten ist eigentlich nur, dass "MaintenanceLeave" mit "Quit" beendet werden muss,
wenn und nachdem Sie die alte Version des Produktes deinstalliert haben.
Eine kleine Demonstration sowie die erforderliche Headerdatei "version.nsh" finden
Sie in den Beispielen zu dieser Dokumentation. Die Headerdatei steht Ihnen fr Ihre
eigenen Setups zur Verfgung.
Mein Dank geht an Joost Verburg, der im NSIS-Forum meinen umstndlichen
Denkansatz zur Versionsprfung mit seinem einfacheren Vorschlag entwirrt hat.

79

Nullsoft Scriptable Install System

Patches mit NSIS


Fr dieses Beispiel bentigen Sie das VPatch-Plugin fr NSIS, das beispielsweise ab
Beta 4 von NSIS 2.0 integriert ist.

Was sind Patches? Und wozu braucht man so etwas?


Patches sind kleine Aktualisierungen, die im Gegensatz zu Upgrades eine installierte oder
zumindest vorhandene Version einer Anwendung voraussetzen. Ein Patch enthlt in den meisten
Fllen nmlich nur eine Art "Liste" mit den Unterschieden zwischen der alten und neuen Version.
Dadurch ist ein Patch meist sehr klein, erwartet auf der anderen Seite aber auch eine bestimmte
installierte Version der Anwendung.
Empfehlenswert sind Patches, wenn Sie eine oder mehrere Anwendungen nur aktualisieren wollen,
um evtl. aufgetretene Probleme zu verhindern. Fr solche Mini-Updates lohnt sich meist ein
Upgrade oder ein komplett neues Setup nicht.

Die Patchdateien erstellen


Zunchst mssen Sie mit dem Hilfsprogramm "GenPat.exe", das zum VPatch-Plugin gehrt, den
eigentlichen Patch erzeugen. Diese Patchdatei enthlt dann die Unterschiede der alten und der
neuen Version
GenPatch AlteAnwendung.exe NeueAnwendung.exe Patch.pat
Auf die gleiche Weise verfahren Sie mit allen Dateien, die Sie aktualisieren wollen. Ich gebe zu,
dieser Weg ist ein bisschen umstndlich. Aber wenn Sie mehr als 20 Dateien aktualisieren mssen,
dann wrde ich Ihnen ohnehin zu einem Upgrade im klassischen Sinn raten.

Die Dateien aktualisieren


Auf die Grundlagen werde ich an der Stelle nicht mehr eingehen. Sie bentigen nmlich ein
normales Skript, das Sie entsprechend vorbereiten. Hier ist nur der Aktualisierungsprozess an sich
wichtig. Beachten Sie bitte nur, dass Sie fr den Patch normalerweise keinen Deinstaller bentigen!
Sollte dies allerdings erforderlich sein, um evtl. neu hinzugefgte Dateien zu lschen, die vom
originalen Deinstaller nicht bercksichtigt werden, dann verzichten Sie bitte darauf, den Deinstaller
zu aktualisieren. Erstellen Sie stattdessen einen neuen, der auch die Schritte des originalen
Deinstallers enthlt.
Zurck zum Thema Die eben erzeugten Patchdateien nehmen Sie bitte in Ihr Skript auf. Das Muster kennen Sie
Section "-Patch"
SectionIn RO
SetOutPath $INSTDIR
File "Anwendung.exe.pat"
File "Liesmich.txt.pat"
File "Bibliothek.dll.pat"

80

Nullsoft Scriptable Install System

So weit, so gut. Nach dem Entpacken der Dateien in den Zielordner, knnen Sie das VPatch-Plugin
aufrufen und die Originaldateien aktualisieren lassen. Sie sollten das aber zumindest von der
Existenz der jeweiligen Patchdatei abhngig machen, beispielsweise
IfFileExists "$INSTDIR\Anwendung.exe.pat" 0 +8
DetailPrint "aktualisiere Anwendung.exe ..."
vpatch::vpatchfile "$INSTDIR\Anwendung.exe.pat" \
"$INSTDIR\Anwendung.exe" "$INSTDIR\Anwendung.neu"
Zu beachten ist, dass Sie beim Aufruf des Plugins zuerst den Namen der Patchdatei angeben.
Dann folgt der Name der Datei, die Sie aktualisieren wollen. Und zum Schluss geben Sie einen
temporren Namen fr die neue Datei an. Es ist nmlich nicht mglich, den Dateinamen
beizubehalten!
Wenn die Aktualisierung der Datei erfolgreich war, liefert das Plugin OK als Ergebnis zurck. Davon
abhngig sollten Sie die weiteren Schritte machen: das Lschen der alten Anwendung, und das
Umbenennen der neuen
Pop $R0
DetailPrint "$R0"
StrCmp $R0 "OK" 0 +3
Delete "$INSTDIR\Anwendung.exe"
Rename "$INSTDIR\Anwendung.neu" "Anwendung.exe"
Sie knnen hier auch das "/REBOOTOK"-Flag benutzen, falls es sich um Dateien handelt, die zur
Zeit der Installation benutzt werden und daher nicht gelscht und umbenannt werden knnen.
Sofern notwendig wird daher nach der Installation des Patches ein Neustart ausgelst
Delete /REBOOTOK "$INSTDIR\Anwendung.exe"
Rename /REBOOTOK "$INSTDIR\Anwendung.neu" "Anwendung.exe"
Auf diese Weise verfahren Sie bitte mit den anderen zu aktualisierenden Dateien.
Im letzten Schritt sollten Sie die kopierten Patchdateien dann einfach lschen
Delete "$INSTDIR\*.pat"
SectionEnd

81

Nullsoft Scriptable Install System

Und wenn es zwei verschiedene Versionen der Anwendung gibt?


Wenn Sie einen Patch erzeugen wollen, der zwei verschiedene Versionen Ihrer Anwendung
bercksichtigt, dann ist das natrlich auch mglich. Nehmen wir als Beispiel an, Sie htten die
normale Anwendung und evtl. eine kostenlose Variante mit weniger Funktionen, die Sie auf Grund
eines Fehlers aber auch anpassen mssen.
Das Prinzip ist relativ einfach: Sie erstellen fr beide Versionen jeweils eine Patchdatei und binden
beide in das Skript ein,
File "Anwendung.exe.pat"
File "Anwendung.freeware.pat"
Dann versuchen Sie, die Anwendung zunchst mit einem Patch zu aktualisieren
DetailPrint "aktualisiere Anwendung "
vpatch:vpatchfile "$INSTDIR\Anwendung.exe.pat" \
"Anwendung.exe" "Anwendung.neu"
Schlgt die Aktualisierung fehl (das knnen Sie anhand des Rckgabewertes ermitteln), dann
versuchen Sie Ihr Glck mit dem nchsten Patch
Pop $R0
StrCmp $R0 "OK" +2
vpatch::vpatchfile "$INSTDIR\Anwendung.freeware.pat" \
"Anwendung.exe" "Anwendung.neu"

82

Nullsoft Scriptable Install System

Dateien downloaden
Eine spezielle Form des Setup ist das so genannte Web-Setup. Wie auch immer Sie es nennen
wollen, die Idee ist, dass die bentigten Dateien von einem Server im Internet heruntergeladen
werden.
Der Vorteil dieser Methode ist, dass das Setup selbst recht klein ist, da es normalerweise keine
Dateien enthlt, die entpackt werden mssten. Nachteil ist, dass die Installation (speziell der
Download) von der Gre der Dateien abhngt und daher evtl. hohe Internetkosten verursachen
kann.
Fr den Download bentigen wir das Plugin NsisDl (NSIS Download). Diese DLL muss mit dem
Namen der gewnschten Funktion aufgerufen werden, dann folgen die komplette URL der Datei
auf dem Server und der lokale Name, unter dem die Datei gespeichert werden soll, beispielsweise
nsisdl::download "${URL}/NSIS.pdf" "NSIS.pdf "
Der Rckgabewert der Funktion ist entweder "cancel", "success" oder ein String mit der Fehlerbeschreibung und lsst sich wie folgt abfragen
Pop $R0
StrCmp $R0 "cancel" 0 +3
MessageBox MB_OK "Download abgebrochen"
Quit
StrCmp $R0 "success" +3
MessageBox MB_OK|MB_ICONEXCLAMATION \
"Fehlermeldung: $\"$R0$\""
Quit

Timeout
Zustzlich lsst sich auch ein Timeout-Wert angeben, nach dessen Ablauf der Versuch des
Downloads abgebrochen wird. Das kann bei Verbindungsproblemen hilfreich sein. Benutzen Sie
dazu einfach den Parameter "/TIMEOUT" mit dem gewnschten Wert in Millisekunden
nsisdl::download /TIMEOUT=30000 "${URL}/NSIS.pdf" "NSIS.pdf"
Sollte in diesem Fall nach 30 Sekunden keine Verbindung zustande gekommen oder kein
Download mglich sein, wird der Versuch abgebrochen.

83

Nullsoft Scriptable Install System

Das Interface auf Deutsch


Die Meldungen und das Interface des Plugins sind standardmig englischsprachig. Mit Hilfe des
Parameters "/TRANSLATE" lsst sich aber immerhin das Interface in jede beliebige Sprache bersetzen. Dazu ist lediglich die Reihenfolge der Texte zu beachten
Name
downloading
connecting
second
minute
hour
plural
progress
remaining

Bedeutung
Text whrend des Downloads
Text whrend des Verbindungsversuches
Landestypischer Text fr "Sekunde"
Landestypischer Text fr "Minute"
Landestypischer Text fr "Stunde"
Landestypische Angabe des Plural. Im Fall von Deutsch wre das
beispielsweise das "n", weil aus "Stunde" im Plural "Stunden" wird.
Text fr die Anzeige der Gre der Datei
Text fr die Anzeige des Restes der Datei

Nun dienen diese Parameter aber nur als Platzhalter. Das bedeutet, Sie mssen Sie nicht benutzen
sondern gleich den gewnschten Text angeben. In der Readme-Datei des Plugins finden Sie die
Standardmeldungen, an denen Sie sich orientieren sollten - speziell was die Formatstrings angeht,
die spter durch Dateinamen, Grenangaben usw. ersetzt werden.
Im Fall des deutschen Interfaces wrde der Aufruf wie folgt aussehen
nsisdl::download /TRANSLATE "Download von %s" \
"verbinde ..." \
"Sekunde" \
"Minute" \
"Stunde"
"n" \
"%d kB (%d%%) von %d kB @ %d.%01d kB/s" \
"(%d %s%s brig)" \
"${URL}/inno.pdf" "inno.pdf"
Zur besseren bersicht habe ich die einzelnen Parameter in eigene Zeilen geschrieben. Beachten
Sie bitte auerdem, dass Sie den Parameter "/TRANSLATE" (und damit die bersetzten Texte) vor
"/TIMEOUT" verwenden mssen.

Das Beispiel "websetup.nsi" demonstriert Ihnen den Download anhand zweier


Dateien meiner Homepage.

84