Précédent | Accueil | Suivant

Appendice C: Informations utiles

C.1 Compilation des sources NSIS

Les fichiers source de NSIS sont inclues dans chaque distribution NSIS officielle, aussi bien que dans les versions de dévelopment. The binary files distributed with the Les fichiers binaires de NSIS sont compilés avec le compilateur Microsoft Visual C++ 6.0. Les sources ont aussi été testée pour être compatible avec le compilateur Microsoft Visual C++ .NET 2002/2003. La distribution NSIS inclu les fichiers de projet Microsoft Visual C++ 6.0, Microsoft Visual C++ .NET 2002/2003 convertissant automatiquement ces fichiers dans le nouveau format.

Si vous ne possédez pas Microsoft Visual C++, vous pouvez télécharger gratuitement le .NET Framework SDK (nécessite Windows 2000/XP/Server 2003), incluant les derniers compilateurs Microsoft. Ce SDK n'inclu pas les bibliothèques/entêtes de l'API Win32, et vous devez donc aussi télécharger le dernier Platform SDK. Voir la documentation de Microsoft pour plus d'informations sur l'utilisation du compilateur en ligne de commandes et sur les outils d'édition des liens.

Des versions précédentes de NSIS ont été décrites comme fonctionnant avec le compilateur MinGW, cependant, nous n'avons pas un makefile à jour. Si vous utilisez MinGW ou un autre compilateur comme Borland C++ Builder ou Open Watcom C/C++ ou voulez fournir des makefiles ou des fichiers de projet, veuillez nous laisser un mot sur le Forum NSIS.

Notes importantes pour les utilisateurs de Microsoft Visual C++ 6.0 : Vous devriez installer la dernière Platform SDK. A cause de failles dans les bibliothèques distribuées avec Microsoft Visual C++ 6.0, ne pas installer la Platform SDK entrainera des crashs lors de l'utilisation de la commande CopyFiles, voir ce sujet du forum pour plus d'informations. L'installation du Processor Pack est aussi hautement recommandé pour décroitre la taille de l'entête de l'installation.

C.2 Niveaux d'erreur

Comme les autres applications, une installation conçue par NSIS retourne un niveau d'erreur comme résultat de son exécution. La vérification du niveau d'erreur peut être utile si vous appellez une installation NSIS depuis une autre aplication ou installation.

Installations normales :

Installations silencieuses :

C.3 Ajouter des informations de désinstallation dans Ajout/Suppression de programmes

Créez une clé avec votre nom de produit sous HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall pour ajouter une entrée dans la section "Ajout/Suppression de programmes" du Panneau de Configuration. Pour Windows NT (NT4/2000/XP), il est aussi possible de créer une clé dans la ruche HKCU, afin que cela n'apparaisse que pour l'utilisateur courant. Il existe plusieurs valeurs que vous pouvez créer afin de donner des informations sur votre application et la désinstallation. Ecrivez une valeur en utilisant la commande WriteRegStr (pour les chaînes de caractères) ou la commande WriteRegDWORD (pour les valeurs DWORD). Par exemple :

WriteRegStr HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\Product" "DisplayName" "Nom de votre application"

Valeurs requises

DisplayName (chaîne) - Nom de l'application
UninstallString (chaîne) - Chemin et fichier de la désinstallation. Vous devriez toujours mettrez le répertoire entre guillemets pour être certain que les espaces n'empêcheront pas Windows à retrouver l'installation.

Valeurs optionnelles

Certaines de ces valeurs ne seront pas utilisées par d'anciennes versions de Windows.

InstallLocation (chaîne) - Répertoire d'installation ($INSTDIR)
DisplayIcon (chaîne) - Chemin, fichier et index de l'icône à afficher près du nom de votre application

Publisher (chaîne) - (Société) nom du distributeur

ModifyPath (chaîne) - Chemin et fichier du programme de modification de l'application
InstallSource (chaîne) - Emplacement d'où l'application a été installé

ProductID (chaîne) - Identifiant Produit de l'application
RegOwner (chaîne) - Utilisateur enregistré de l'application
RegCompany (chaîne) - Société enregistrée de l'application

HelpLink (chaîne) - Lien vers le site web support
HelpTelephone (string) - Numéro de téléphone du support

URLUpdateInfo (chaîne) - Lien vers le site web pour des mises à jour de l'application
URLInfoAbout (chaîne) - Lien vers le site web de l'application

DisplayVersion (string) - Version affichée de l'application
VersionMajor (DWORD) - Numéro de version majeur de l'application
VersionMinor (DWORD) - Numéro de version mineur de l'application

NoModify (DWORD) - 1 si la désinstallation n'a aucune option de modification de l'application installée
NoRepair (DWORD) - 1 si la désinstallation n'a aucune option de réparation de l'application installée

Si à la fois NoModify et NoRepair sont définis à 1, le bouton affiche "Supprimer" au lieu de "Modifier/Supprimer".

C.4 Comment installer les runtimes VB6

Le meilleur moyen d'installer les runtimes VB6 est d'utiliser la macro UpgradeDLL pour mettre à jour les fichiers DLL, et la fonction AddSharedDLL pour incrémenter le compteur des DLL partagées.

Utilisez Modern UI avec une page Terminé pour demander à l'utilisateur de redémarrer si nécessaire, ou utilisez IfRebootFlag et créez votre propre page ou boîte de dialogue.

Pour obtenir les fichiers runtime VB6, vous pouvez extraire les fichiers depuis vbrun60sp5.exe en utilisant un gestionnaire d'archives supportant la compression CAB ou, si vous avez installé la dernière version, copiez les fichiers depuis votre répertoire système. Vous avez besoin des fichiers suivants :

Asycfilt.dll
Comcat.dll
Msvbvm60.dll
Oleaut32.dll
Olepro32.dll
Stdole2.tlb

Pendant la désinstallation, utilisez la fonction un.DecrementSharedDLL ci-dessous oour décrémenter le compteur des DLL partagées (ne jamais supprimer le fichier, car le compteur des DLL partagées n'est pas suffisement fiable pour des fichiers aussi importants).

!include "UpgradeDLL.nsh"

!define VBFILESDIR "C:\Windows\System" ; Emplacement des fichiers runtime VB6

Section "Install VB DLLs"

  !insertmacro UpgradeDLL ${VBFILESDIR}\Comcat.dll $SYSDIR\Comcat.dll $SYSDIR
  !insertmacro UpgradeDLL ${VBFILESDIR}\Msvbvm60.dll $SYSDIR\Msvbvm60.dll $SYSDIR
  !insertmacro UpgradeDLL ${VBFILESDIR}\Oleaut32.dll $SYSDIR\Oleaut32.dll $SYSDIR
  !insertmacro UpgradeDLL ${VBFILESDIR}\Olepro32.dll $SYSDIR\Olepro32.dll $SYSDIR

  !define UPGRADEDLL_NOREGISTER
    !insertmacro UpgradeDLL ${VBFILESDIR}\Asycfilt.dll $SYSDIR\Asycfilt.dll $SYSDIR
    !insertmacro UpgradeDLL ${VBFILESDIR}\Stdole2.tlb $SYSDIR\Stdole2.tlb $SYSDIR
  !undef UPGRADEDLL_NOREGISTER

  ;Only iease DLL count on new installation
  ;Replace myprog.exe or use another detection method
  IfFileExists $INSTDIR\myprog.exe skipAddSharedDLL
    Push $SYSDIR\Asycfilt.dll
    Call AddSharedDLL
    Push $SYSDIR\Comcat.dll
    Call AddSharedDLL
    Push $SYSDIR\Msvbvm60.dll
    Call AddSharedDLL
    Push $SYSDIR\Oleaut32.dll
    Call AddSharedDLL
    Push $SYSDIR\Olepro32.dll
    Call AddSharedDLL
    Push $SYSDIR\Stdole2.tlb
    Call AddSharedDLL
  skipAddSharedDLL:

SectionEnd

Section "Uninstall"

  Push $SYSDIR\Asycfilt.dll
  Call un.DecrementSharedDLL
  Push $SYSDIR\Comcat.dll
  Call un.DecrementSharedDLL
  Push $SYSDIR\Msvbvm60.dll
  Call un.DecrementSharedDLL
  Push $SYSDIR\Oleaut32.dll
  Call un.DecrementSharedDLL
  Push $SYSDIR\Olepro32.dll
  Call un.DecrementSharedDLL
  Push $SYSDIR\Stdole2.tlb
  Call un.DecrementSharedDLL

SectionEnd

Function AddSharedDLL
  Exch $R1
  Push $R0
    ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1
    IntOp $R0 $R0 + 1
    WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 $R0
   Pop $R0
   Pop $R1
 FunctionEnd

Function un.DecrementSharedDLL
  Exch $R1
  Push $R0
  ReadRegDword $R0 HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1
  StrCmp $R0 "" done
    IntOp $R0 $R0 - 1
    IntCmp $R0 0 rk rk uk
    rk:
      DeleteRegValue HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1
      Goto done
    uk:
      WriteRegDWORD HKLM Software\Microsoft\Windows\CurrentVersion\SharedDLLs $R1 $R0
  done:
  Pop $R0
  Pop $R1
FunctionEnd

C.5 Appel d'une DLL externe en utilisant le plugin System.dll

Certains processus d'installation sont requis pour appeler des fonctions contenues dans les DLLs tiers. Un exemple évident est lors de l'installation d'un conduit Palm(TM).

Et pendant ce temps, System.dll
Le plugin System.dll (par Brainsucker) permet l'appel de DLLs externes en fournissant la fonction 'Call'. Il existe bien d'autres fonctions fournies par System.dll, mais elles ne seront pas couvertes ici. Pour plus d'informations sur les autres fonctions, vérouillez votre porte, décrochez le téléphone, et approchez lentement (en faisant des détours pour être certain de ne pas être suivi) du répertoire Contrib/System, et lisez-y les documentations.

Types de données
System.dll reconnait les types de données suivant :

Correspondances entre les variables System.dll et les variables de script NSIS
Il n'y a aucun intérêt à être capable d'appeler des fonctions externes s'il n'est pas possible de récupérer des données. System.dll fait correspondre les variables des fonctions en variables NSIS de cette mani ère:

NSIS $0..$9 devient System.dll r0..r9 NSIS $R0..$R9 devient System.dll r10..r19

Chaque paramètre est spécifié par un type, une entré et une sortie. Pour sauter l'entrée ou la sortie, utilisez un point. Par exemple :

String (pointeur sur un tableau de caractères), l'entrée est 'Joyeuses Paques' :

t 'Joyeuses Paques'

String (pointeur sur un tableau de caractères), l'entrée est prise depuis $5 et les modifications du tableau faites par l'appel sont sauvées dans $R8 :

t r5R8

Pointeur sur un entier, la valuer est prise depuis $1 et mise dans $2 :

*i r1r2

Pointeur sur un entier 64 bits, la sortie est mise dans la pile, aucune entrée :

*l .s

Utilisation de System.dll::Call Pour appeler une fonction dans une DLL tiers, la fonction Call est utilisée comme cela :

System::Call 'VotreDLL::SuperFonction(i, *i, t) i(r0, .r1, r2) .r3'

la section '(r0, .r1, r2) .r3' à la fin correpond aux paramètres passés entre votre DLL et votre script NSIS. Comme vous pouvez le voir dans cette liste de paramètres, types et type entrées/sorties peuvent être séparés. Chaque bloc de "(liste de paramètres) valeur de retour" écrase et/ou s'ajoute au précédent. Dans ce cas, le premier bloc spécifit le type et le second, les entrées/sorties.

Avant de coder comme un fou votre script NSIS
Avant de vous attaquer au code NSIS, vous devez connaître le prototype complet de la fonction que vous allez appeler. Pour les besoins de cet exemple, nous utiliserons la fonction 'CmGetHotSyncExecPath' pour 'CondMgr.dll' de Palm. Cette fonction est utilisée pour retourner le répertoire complet de 'HotSync.exe'.

Définition de la fonction

int CmGetHotSyncExecPath(TCHAR *pPath, int *piSize);

valeur de retour :

Ainsi, si le tampon est trop petit, la valeur dans *int est la taille (en TCHAR) que le tampon devrait être.

Cette définition de fonction correspond pour System.dll à la définition suivante :

CmGetHotSyncExecPath(t, *i) i

ex. Elle prend un variable texte, un pointeur sur un entier, et renvoit un entier.

Utilisation d'une fonction DLL externe
Maintenant que nous avons vu comment fonctionnait la fonction, et comment elle était convertie en format System.dll, nous pouvons utiliser la fonction dans un script NSIS.

Tout d'abord, il est recommandé de paramètrer 'PluginUnload' à off avant de faire plusieurs appels avec System.dll. D'après Brainsucker (et d'autres), cela accélérera l'exécution du package d'installation.

Ensuite, vous devez modifier le répertoire de destination vers celui contenant la DLL que vous voulez utiliser. Cela peut tout de même fonctionner si la DLL est dans le répertoire système, mais cela n'a pas été testé.

Le fragment de code suivant installera 'condmgr.dll' dans un répertoire temporaire, exécutera la fonction CmGetHotSyncExecPath, affichera les données retournées et déchargera finalement le plugin System.dll. Enregistrez ce script

; **** snip ****
SetPluginUnload  alwaysoff

Function loadDll

  SetOutPath $TEMP\eInspect             ; créé un répertoire temporaire
  File bin\CondMgr.dll                  ; copie de la dll
  StrCpy $1 ${NSIS_MAX_STRLEN}          ; définition mémoire de $0
  System::Call 'CondMgr::CmGetHotSyncExecPath(t, *i) i(.r0, r1r1).r2'
  DetailPrint 'Rep : "$0"'
  DetailPrint "Taille rep : $1"
  DetailPrint "Valeur de retour : $2"

; le dernier appel de plugin de doit pas spécifier /NOUNLOAD pour que NSIS soit capable de supprimer
; la DLL temporaire

  SetPluginUnload manual
; ne rien faire (mais laisser l'installation décharger System.dll)
  System::Free 0
FunctionEnd
; **** snip ****

cette fonction produit la sortie suivante dans la page 'Détails' :

destination : c:\windows\TEMP\eInspect
Extraction : CondMgr.dll
Rep : "C:\Dave\palm\Hotsync.exe"
Taille rep : 24
Valeur de retour : 0

Ecrit par djc

Accords & Remerciements
Une tonne de mercis à kichik et Sunjammer pour avoir passé beaucoup de temps à résoudre ce problème. Merci aussi à brainsucker pour créer le plugin System.dll, et c'est normal. Bonne chance !

C.6 Placer le contenu dans la fenêtre Détails dans un fichier

Cette fonction va placer le contenu du journal de l'installation (Détails) dans le fichier de votre choix. J'ai créé cette fonction pour Afrow_UK qui recherchait un moyen de placer le journal dans un fichier, dans ce sujet du forum.

Pour l'utiliser, placez le nom du fichier dans la pile et appellez-là. Cela placera (mais vous l'aurez compris) le contenu du journal dans le fichier spécifié. Par exemple :

GetTempFileName $0
Push $0
Call DumpLog

Voici la fonction :

!define LVM_GETITEMCOUNT 0x1004
!define LVM_GETITEMTEXT 0x102D

Function DumpLog
  Exch $5
  Push $0
  Push $1
  Push $2
  Push $3
  Push $4
  Push $6

  FindWindow $0 "#32770" "" $HWNDPARENT
  GetDlgItem $0 $0 1016
  StrCmp $0 0 error
  FileOpen $5 $5 "w"
  StrCmp $5 0 error
    SendMessage $0 ${LVM_GETITEMCOUNT} 0 0 $6
    System::Alloc ${NSIS_MAX_STRLEN}
    Pop $3
    StrCpy $2 0
    System::Call "*(i, i, i, i, i, i, i, i, i) i \
      (0, 0, 0, 0, 0, r3, ${NSIS_MAX_STRLEN}) .r1"
    loop: StrCmp $2 $6 done
      System::Call "User32::SendMessageA(i, i, i, i) i \
        ($0, ${LVM_GETITEMTEXT}, $2, r1)"
      System::Call "*$3(&t${NSIS_MAX_STRLEN} .r4)"
      FileWrite $5 "$4$\r$\n"
      IntOp $2 $2 + 1
      Goto loop
    done:
      FileClose $5
      System::Free $1
      System::Free $3
      Goto exit
  error:
    MessageBox MB_OK error
  exit:
    Pop $6
    Pop $4
    Pop $3
    Pop $2
    Pop $1
    Pop $0
    Exch $5
FunctionEnd

Ecrit par KiCHiK

C.7 Comment lire des valeurs REG_MULTI_SZValues

J'ai écris ce script pour aider rpetges dans ce sujet du forum. Cela va lire une valeur dans le registre, du type REG_MULTI_SZ, et l'afficher. N'oubliez pas de modifier là où il est écrit "Modifier ici !" lorsque vous testerez ce script. LEs valeurs doivent pointer sur une valeur REG_MULTI_SZ ou l'exemple génerera une erreur.

OutFile "Lecteur REG_MULTI_SZ.exe"

Name "Lecteur REG_MULTI_SZ"

ShowInstDetails show

!define HKEY_CLASSES_ROOT        0x80000000
!define HKEY_CURRENT_USER        0x80000001
!define HKEY_LOCAL_MACHINE       0x80000002
!define HKEY_USERS               0x80000003
!define HKEY_PERFORMANCE_DATA    0x80000004
!define HKEY_PERFORMANCE_TEXT    0x80000050
!define HKEY_PERFORMANCE_NLSTEXT 0x80000060
!define HKEY_CURRENT_CONFIG      0x80000005
!define HKEY_DYN_DATA            0x80000006

!define KEY_QUERY_VALUE          0x0001
!define KEY_ENUMERATE_SUB_KEYS   0x0008

!define REG_NONE                 0
!define REG_SZ                   1
!define REG_EXPAND_SZ            2
!define REG_BINARY               3
!define REG_DWORD                4
!define REG_DWORD_LITTLE_ENDIAN  4
!define REG_DWORD_BIG_ENDIAN     5
!define REG_LINK                 6
!define REG_MULTI_SZ             7

!define RegOpenKeyEx     "Advapi32::RegOpenKeyExA(i, t, i, i, i) i"
!define RegQueryValueEx  "Advapi32::RegQueryValueExA(i, t, i, i, i, i, i) i"
!define RegCloseKey      "Advapi32::RegCloseKeyA(i) i"

####### Modifier ici !

!define ROOT_KEY         ${HKEY_CURRENT_USER}
!define SUB_KEY          "Software\Joe Software"
!define VALUE            "Strings"

####### Ne modifiez plus rien. Ce n'est plus écrit "Modifier ici !", je le sais bien, c'est moi qui l'ai écrit

Section "Lecture"
  StrCpy $0 ""
  StrCpy $1 ""
  StrCpy $2 ""
  StrCpy $3 ""
  SetPluginUnload alwaysoff
  System::Call "*(i) i (0) .r0"
  System::Call "*(i) i (0) .r1"
  System::Call "*(i) i (0) .r2"
  System::Call "${RegOpenKeyEx}(${ROOT_KEY}, '${SUB_KEY}', \
    0, ${KEY_QUERY_VALUE}|${KEY_ENUMERATE_SUB_KEYS}, r0) .r3"

  StrCmp $3 0 goon
    MessageBox MB_OK|MB_ICONSTOP "Impossible d'ouvrir la clé du registre ! ($3)"
    Goto done
goon:

  System::Call "*$0(&i4 .r4)"
  System::Call "${RegQueryValueEx}(r4, '${VALUE}', 0, r1, 0, r2) .r3"

  StrCmp $3 0 read
    MessageBox MB_OK|MB_ICONSTOP "Impossible de demander la valeur ! ($3)"
    Goto done

read:

  System::Call "*$1(&i4 .r3)"

  StrCmp $3 ${REG_MULTI_SZ} multisz
    MessageBox MB_OK|MB_ICONSTOP "La valeur du registre n'est pas du type SZ_MULTI_SZ ! ($3)"
    Goto done

multisz:

  System::Call "*$2(&i4 .r3)"

  StrCmp $3 0 0 multiszalloc
    MessageBox MB_OK|MB_ICONSTOP "La valeur du registre est vide ! ($3)"
    Goto done

multiszalloc:

  System::Free $1
  System::Alloc $3
  Pop $1

  StrCmp $1 0 0 multiszget
    MessageBox MB_OK|MB_ICONSTOP "Impossible d'allouer suffisement de mémoire ! ($3)"
    Goto done

multiszget:

  System::Call "${RegQueryValueEx}(r4, 'bla', 0, 0, r1, r2) .r3"

  StrCmp $3 0 multiszprocess
    MessageBox MB_OK|MB_ICONSTOP "Impossible de demander la valeur dans le registre ! ($3)[2]"
    Goto done

multiszprocess:

  StrCpy $4 $1

  loop:

    System::Call "*$4(&t${NSIS_MAX_STRLEN} .r3)"
    StrCmp $3 "" done
    DetailPrint $3
    StrLen $5 $3
    IntOp $4 $4 + $5
    IntOp $4 $4 + 1
    Goto loop

done:

  System::Free $2
  System::Free $1

  StrCmp $0 0 noClose
    System::Call "${RegCloseKey}(r0)"

noClose:

  SetPluginUnload manual
  System::Free $0
SectionEnd

Ecrit par KiCHiK

Précédent | Accueil | Suivant