Introduction
On trouve sur le marché de nombreux logiciels permettant de créer une procédure d'installation de votre programme, qui copient vos fichiers dans un dossier spécial, modifient éventuellement la base de registre etc. Les produits BORLAND C++Builder et Delphi contiennent d'ailleurs un tel logiciel nommé InstallShield. Cependant ces logiciels présentent un inconvénient qu'est la taille du programme d'installation. Bien sûr ces logiciels compressent tous vos fichiers mais ils rajoutent également leur propre interface graphique qui prend beaucoup de place. Par exemple pour InstallShield il faut compter environ 400ko en plus de vos fichiers non compressés … D'autres logiciels donnent de meilleurs résultats mais je n'ai pas réussi à en trouver un gratuit et qui permette de modifier la base de registre.C'est pourquoi j'ai déjà voulu utiliser les fichiers INF, qui ont justement pour but de créer des scripts d'installation simples. J'ai dû les coupler à des instructions dans le programme pour avoir plus de possibilités, mais finalement ceux-ci ne marchent qu'à moitié et je me suis rendu compte qu'il était bien plus simple et efficace de programmer complètement l'installation dans le programme même.
L'utilisateur doit simplement décompresser les fichiers dans le dossier dans lequel il souhaite installer votre programme, puis exécuter le programme qui s'installera tout seul. L'utilisateur peut également déplacer le logiciel puisqu'il le détectera et se réinstallera automatiquement à la première exécution, et la désinstallation peut se faire à travers la boîte de dialogue "Ajout/Suppression de programmes" de Windows, ou par une commande dans votre logiciel.
Cette description s'applique toujours à BORLAND C++Builder et Delphi, et les exemples de codes seront comme d'habitude en vert foncé pour C++Builder et en rouge foncé pour Delphi.
Outils nécessaires
Accéder à la base de registre
Il est très facile d'accéder à la base de registre de Windows avec Delphi et C++Builder, qui proposent des routines dédiées.Il faut tout d'abord inclure la bibliothèque Registry :
#include <registry.hpp>
uses registry;
Puis créer un objet TRegistry :
TRegistry *reg = new TRegistry;
Var reg: TRegistry; reg := TRegistry.Create;
et l'utiliser :
reg->RootKey = HKEY_LOCAL_MACHINE; // ou HKEY_CLASSES_ROOT, HKEY_CURRENT_USER etc ... reg->OpenKey(nomClé, CréerSiExistePas?); reg->WriteString(nomValeur, valeur); valeur = reg->ReadString(nomValeur); reg->CloseKey();
reg.RootKey := HKEY_LOCAL_MACHINE; reg.OpenKey(nomClé, CréerSiExistePas?); reg.WriteString(nomValeur, valeur); valeur := reg.ReadString(nomValeur); reg.CloseKey;
Récupérer les paramètres de la ligne de commande
Delphi et C++Builder fournissent une fonction qui permet de récupérer les valeurs passées en paramètres à l'application à l'exécution : ParamStr(numParam).La valeur ParamStr(0) contient toujours le chemin complet d'où a été lancée l'application (chemin + nom exécutable).
Les valeurs suivantes contiennent les paramètres suivants qui ont été passés à l'application. La fonction ParamCount() renvoie le nombre de paramètres qui ont été passés à l'application.
Gestion de fichiers
Effacer un fichierDeleteFile(nomFichier);
DeleteFile(nomFichier);Cependant vous ne pourrez pas supprimer l'exécutable puisqu'il est en cours d'exécution. Le mieux est de proposer à l'utilisateur de lui ouvrir le répertoire d'installation pour les supprimer manuellement.
Déplacer un fichier
MoveFile(nomFichier1,nomFichier2); // nomFichier.c_str() si nomFichier variable AnsiString (et pas constante "")
MoveFile(nomFichier1,nomFichier2); // PChar(nomFichier) si nomFichier variable String (et pas constante '')Copier un fichier
CopyFile(nomFichier1,nomFichier2); // nomFichier.c_str
CopyFile(nomFichier1,nomFichier2); // PChar(NomFichier)Renommer un fichier
RenameFile(nomFichier1,nomFichier2);
RenameFile(nomFichier1,nomFichier2);Executer un fichier
#include <shellAPI.h> ShellExecute(0, NULL, nomFichier, NULL, NULL, SW_NORMAL);
uses shellAPI; ShellExecute(0, nil, nomFichier, nil, nil, SW_NORMAL);Attention, si nomFichier est une variable chaîne (et pas une constante), vous devez la convertir en tableau de char :
nomFichier.c_str()
PChar(nomFichier)Vous pouvez d'ailleurs utiliser cette commande pour une adresse email (en la précédant de 'mailto:'), ou d'une adresse internet (en la précédant de 'http://').
Autres
Boites de messageIl peut être intéressant de demander confirmation, ou d'informer l'utilisateur sur le déroulement des opérations :
if (MessageDlg("Voulez-vous effacer les entrées du registre ?", mtConfirmation, mbYesNoCancel, 0) == mrCancel) Application->Terminate(); ShowMessage("L'opération s'est bien déroulée");
If MessageDlg('Voulez-vous effacer les entrées du registre ?', mtConfirmation, mbYesNoCancel, 0) = mrCancel Then Application.Terminate; ShowMessage('L''opération s'est bien déroulée');Consultez l'aide pour le détail des paramètres possibles. Icônes (ressources)
Il est possible d'inclure plusieurs icônes dans l'exécutable, dont on peut se servir par exemple pour registrer un type de fichier. Il faut pour cela créer un fichier ressource .res à l'aide de l'éditeur d'image, accessible par le menu Outils, puis créer une ou plusieurs icônes.
Il faut ensuite inclure ce fichier ressource au programme, en ajoutant dans le code de la fiche principale :
#pragma resource "icone.res"
{$R fichier.res}
L'installation / désinstallation et le registre
Pour installer correctement une application, il est nécessaire d'écrire dans plusieurs clés, permettant à Windows de savoir que l'application existe, où elle se trouve, comment la désinstaller, si des types de fichier lui sont associés ...Nous allons ici détailler où se trouvent ces clés et ce qu'elles doivent contenir.
Vous pouvez observer le contenu du registre grâce à l'Editeur du registre fourni avec Windows, que vous pouvez lancer en tapant 'regedit' dans la boîte Exécuter du Menu Démarrer.
L'emplacement de l'application
La clé se trouve dans 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\NomExecutable'.NomExecutable est le nom de l'exécutable de votre application, AVEC l'extension .exe, par exemple 'CR-KryptX.exe'.
Il faut écrire deux valeurs dans cette clé, une valeur 'Path' qui contient le dossier d'installation (que l'on peut obtenir par ExtractFilePath(ParamStr(0)), et dans la valeur Défaut (que l'on adresse avec un nom de valeur chaîne nulle '' ou "") le chemin complet de l'exécutable (que l'on peut obtenir par ParamStr(0)).
On se servira de cette clé pour déterminer si l'application a été déplacée et par conséquent réeffectuer l'installation.
La désinstallation
On peut rendre possible la désinstallation par l'intermédiaire de la boîte 'Ajout/Suppression de programmes' de Windows simplement en l'enregistrant dans le registre.La clé se trouve dans 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\NomApplication'.
Il faut écrire deux valeurs dans cette clé, une valeur 'DisplayName' qui contient le nom qui sera affiché dans la boîte, et une valeur 'UninstallString' qui contient la ligne de commande à exécuter quand l'utilisateur voudra désinstaller l'application. Dans notre cas elle sera composée du chemin et nom de l'application (ParamStr(0)) suivi du paramètre 'uninstall' dont on se servira dans l'application pour savoir qu'il faut désinstaller l'application.
La registration de ses propres types de fichiers
Grâce au registre, on peut également registrer ses propres types de fichiers, c'est à dire choisir une extension et affecter aux fichiers une icône, faire en sorte que par un double clic dessus votre application soit lancée automatiquement, ajouter une commande au menu contextuel permettant d'ouvrir un certain type de fichier avec votre application, bref, donner une allure professionnelle à vos logiciels.Toutes les registrations de fichiers se trouvent dans la clé principale HKEY_CLASSES_ROOT.
Il y a ensuite une sous-clé par extension registrée, de la forme '.kpx', qui contient dans sa valeur Défaut le nom d'une autre sous-clé, par exemple fKryptX, qui se trouve toujours dans la même clé principale et dans laquelle se trouvent toutes les informations.
On écrira dans cette clé :
- la valeur Défaut : la description du type de fichier tel que vous voulez qu'il apparaisse dans l'explorateur, tel que 'Fichier crypté CR-KryptX'.
- la sous-clé 'DefaultIcon' contenant :
- la valeur Défaut : l'emplacement de l'icône, par exemple le nom de l'application suivi de l'index de l'icône (voir section suivante).
- la sous-clé 'Shell' contenant :
- une sous-clé de nom de votre choix de l'action à faire sur le fichier (par exemple 'Décrypter') contenant :
- la valeur Défaut : le nom de l'action tel qu'il apparaîtra dans le menu contextuel
- la sous-clé 'command' contenant :
- la valeur Défaut : la ligne de commande pour exécuter votre application : le chemin et nom de votre application suivi de différents paramètres de votre choix (par exemple 'decrypter') et surtout de "%1" (avec les guillemets) qui renvoie en paramètre le nom du fichier à traiter.
- la valeur Défaut : facultative, cette valeur contient l'ordre d'affichage des différentes actions (les noms des sous-clés d'actions séparés par des virgules), la première étant celle par défaut qui est exécutée lors d'un double-clic. Cette valeur est à modifier surtout si votre application est la seule à utliser ce type de fichier afin qu'un double-clic l'exécute.
On peut aussi noter quelques autres sous-clés de HKEY_CLASSES_ROOT importantes de types de fichier, comme la clé '*' qui contient les actions affichées dans le menu contextuel pour tous les types de fichiers, la clé 'unknown' qui concerne tous les types de fichiers non registrées, et la clé 'Folder' pour les répertoires.
Dans tous les cas le mieux pour vous donner une idée est de regarder comment sont faites les clés de types de fichiers connus.
L'implémentation finale (exemple de code complet)
void Installer() { TRegistry *reg = new TRegistry; try { reg->RootKey = HKEY_LOCAL_MACHINE; if (!reg->OpenKey("\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppPaths\\CR-KryptX.exe", false) || (ParamStr(0) != reg->ReadString(""))) {//-- si pas installé du tout ou changé chemin // chemin reg->CloseKey(); reg->OpenKey("\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppPaths\\CR-KryptX.exe", true); reg->WriteString("", ParamStr(0)); reg->WriteString("Path", CheminApp); reg->CloseKey(); // uninstall reg->OpenKey("\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall", false); reg->CreateKey("\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\CR-KryptX"); reg->OpenKey("\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\CR-KryptX", false); reg->WriteString("DisplayName", "CR-KryptX 1.0"); reg->WriteString("UninstallString", ParamStr(0) + " uninstall"); reg->CloseKey(); // registrer .kpx et option crypter pour tous les autres fichiers reg->RootKey = HKEY_CLASSES_ROOT; reg->OpenKey("\\*\\Shell\\CR-KryptX", true); reg->WriteString("", "Crypter avec CR-KryptX"); reg->CloseKey(); reg->OpenKey("\\*\\Shell\\CR-KryptX\\command", true); reg->WriteString("", "\"" + ParamStr(0) + "\"" + " crypter \"%1\""); reg->CloseKey(); reg->OpenKey("\\.kpx", true); reg->WriteString("", "fKryptX"); reg->CloseKey(); reg->OpenKey("\\fKryptX", true); reg->WriteString("", "Fichier crypté CR-KryptX"); reg->CloseKey(); reg->OpenKey("\\fKryptX\\DefaultIcon", true); reg->WriteString("", ParamStr(0) + ",1"); reg->CloseKey(); reg->OpenKey("\\fKryptX\\Shell", true); reg->WriteString("", "Decrypter"); reg->OpenKey("\\fKryptX\\Shell\\Decrypter", true); reg->WriteString("", "Décrypter avec CR-KryptX"); reg->CloseKey(); reg->OpenKey("\\fKryptX\\Shell\\Decrypter\\command", true); reg->WriteString("", "\"" + ParamStr(0) + "\"" + " decrypter \"%1\""); reg->CloseKey(); // clé options if (!reg->KeyExists("\\SOFTWARE\\CR-TEKnologies")) reg->CreateKey("SOFTWARE\\CR-TEKnologies"); if (!reg->KeyExists("\\SOFTWARE\\CR-TEKnologies\\KryptX")) reg->CreateKey("SOFTWARE\\CR-TEKnologies\\XFonte"); reg->OpenKey("\\SOFTWARE\\CR-TEKnologies\\KryptX", true); if (!reg->ValueExists("Langue")) reg->WriteString("Langue", "Français"); reg->CloseKey(); } reg->OpenKey("\\SOFTWARE\\CR-TEKnologies\\KryptX", true); Langue = reg->ReadString("Langue"); } __finally { delete reg; } } void __fastcall TForm1::FormCreate(TObject *Sender) { installer(); if (ParamStr(1) == "decrypter" && LowerCase(ExtractFileExt(ParamStr(2))) == ".kpx") { ... Application->Terminate(); } else if (ParamStr(1) == "crypter") { ... Application->Terminate(); } } void desinstaller() { int res = MessageDlg("Voulez-vous effacer les entrées du registre ?", mtConfirmation, mbYesNoCancel, 0); if (res == mrCancel) return; if (res == mrYes) { TRegistry *reg = new TRegistry; try { reg->RootKey = HKEY_LOCAL_MACHINE; reg->DeleteKey("\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\AppPaths\\CR-KryptX.exe"); reg->DeleteKey("\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\CR-KryptX"); reg->DeleteKey("\\SOFTWARE\\CR-TEKnologies\\KryptX"); reg->OpenKey("\\SOFTWARE\\CR-TEKnologies", true); TRegKeyInfo infos; reg->GetKeyInfo(infos); if (infos.NumSubKeys == 0) reg->DeleteKey("\\SOFTWARE\\CR-TEKnologies"); } __finally { delete reg; } } res = MessageDlg("Vous devez supprimer les fichiers manuellement. Voulez-vous accéder au dossier ?", mtConfirmation, mbYesNoCancel, 0); if (res == mrCancel) return; if (res == mrYes) ShellExecute(0, NULL, CheminApp.c_str(), NULL, NULL, SW_NORMAL); Application->Terminate(); } // dans le source du projet (.cpp) WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int) { try { Application->Initialize(); if (ParamStr(1) == "uninstall") desinstaller(); ... ...
Procedure Installer(); Var reg: TRegistry; Begin reg := TRegistry.Create; Try reg.RootKey := HKEY_LOCAL_MACHINE; If (Not(reg.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\AppPaths\CR-KryptX.exe', false)) Or (ParamStr(0) <> reg.ReadString(''))) Then Begin //-- si pas installé du tout ou changé chemin // chemin reg.CloseKey(); reg.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\AppPaths\CR-KryptX.exe', true); reg.WriteString('', ParamStr(0)); reg.WriteString('Path', CheminApp); reg.CloseKey(); // uninstall reg.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall', false); reg.CreateKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CR-KryptX'); reg.OpenKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CR-KryptX', false); reg.WriteString('DisplayName', 'CR-KryptX 1.0'); reg.WriteString('UninstallString', ParamStr(0) + ' uninstall'); reg.CloseKey(); // registrer .kpx et option crypter pour tous les autres fichiers reg.RootKey := HKEY_CLASSES_ROOT; reg.OpenKey('\*\Shell\CR-KryptX', true); reg.WriteString('', 'Crypter avec CR-KryptX'); reg.CloseKey(); reg.OpenKey('\*\Shell\CR-KryptX\command', true); reg.WriteString('', '"' + ParamStr(0) + '"' + ' crypter "%1"'); reg.CloseKey(); reg.OpenKey('\.kpx', true); reg.WriteString('', 'fKryptX'); reg.CloseKey(); reg.OpenKey('\fKryptX', true); reg.WriteString('', 'Fichier crypté CR-KryptX'); reg.CloseKey(); reg.OpenKey('\fKryptX\DefaultIcon', true); reg.WriteString('', ParamStr(0) + ',1'); reg.CloseKey(); reg.OpenKey('\fKryptX\Shell', true); reg.WriteString('', 'Decrypter'); reg.OpenKey('\fKryptX\Shell\Decrypter', true); reg.WriteString('', 'Décrypter avec CR-KryptX'); reg.CloseKey(); reg.OpenKey('\fKryptX\Shell\Decrypter\command', true); reg.WriteString('', '"' + ParamStr(0) + '"' + ' decrypter "%1"'); reg.CloseKey(); // clé options If Not(reg.KeyExists('\SOFTWARE\CR-TEKnologies')) Then reg.CreateKey('SOFTWARE\CR-TEKnologies'); If Not(reg.KeyExists('\SOFTWARE\CR-TEKnologies\KryptX')) Then reg.CreateKey('SOFTWARE\CR-TEKnologies\XFonte'); reg.OpenKey('\SOFTWARE\CR-TEKnologies\KryptX', true); If Not(reg.ValueExists('Langue')) Then reg.WriteString('Langue', 'Français'); reg.CloseKey(); End; reg.OpenKey('\SOFTWARE\CR-TEKnologies\KryptX', true); Langue := reg.ReadString('Langue'); Finally reg.Free End; End; procedure TForm1.FormCreate(Sender: TObject); Begin installer(); If ((ParamStr(1) = 'decrypter') And (LowerCase(ExtractFileExt(ParamStr(2))) = '.kpx')) Then Begin ... Application.Terminate(); End Else If (ParamStr(1) = 'crypter') Then Begin ... Application.Terminate(); End; End; Procedure desinstaller; Var res: Integer; reg: TRegistry; infos: TRegKeyInfo; Begin res := MessageDlg('Voulez-vous effacer les entrées du registre ?', mtConfirmation, mbYesNoCancel, 0); If (res = mrCancel) Then Exit; If (res = mrYes) Then Begin reg := TRegistry.Create; Try reg.RootKey := HKEY_LOCAL_MACHINE; reg.DeleteKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\AppPaths\CR-KryptX.exe'); reg.DeleteKey('\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\CR-KryptX'); reg.DeleteKey('\SOFTWARE\CR-TEKnologies\KryptX'); reg.OpenKey('\SOFTWARE\CR-TEKnologies', true); reg.GetKeyInfo(infos); If (infos.NumSubKeys = 0) Then reg.DeleteKey('\SOFTWARE\CR-TEKnologies'); Finally reg.Free End; End; res := MessageDlg('Vous devez supprimer les fichiers manuellement. Voulez-vous accéder au dossier ?', mtConfirmation, mbYesNoCancel, 0); If (res = mrCancel) Then Exit; If (res = mrYes) Then ShellExecute(0, nil, PChar(CheminApp), nil, nil, SW_NORMAL); Application.Terminate; End; // Dans le fichier projet (.dpr) Begin Application.Initialize; If ParamStr(1) = 'uninstall' Then desinstaller(); ... End.
Conclusion
Cette méthode d'installation permet donc assez simplement d'installer votre application, en ayant des possibilités très étendues quant à la modification de la base de registre. En revanche elle pêche par la gestion des fichiers, puisque vous ne pourrez pas supprimer l'exécutable, ni créer automatiquement des raccourcis vers votre application.Mais elle garde un avantage indéniable qui est la taille minimale, puisqu'elle n'augmente pas significativement la taille de votre exécutable compressé.
Si vous avez un problème ou une question, n'hésitez pas à me contacter : contact@crteknologies.fr .