Utilisation des FilesMapping sous C++ Builder

ce tutorial démontre l'utilisation des File Mapping avec un exemple d'application

Sources du Programme disponible ici.

Article lu   fois.

L'auteur

Profil ProSite personnel

Liens sociaux

Viadeo Twitter Facebook Share on Google+   

I. Définition

Files Mapping est une des plus puissantes fonctionnalité API Win32 permettant de partager dans la mémoire attribuée à chaque Processus (2 Gb) des zones de mémoires physiques ou de fichiers stockés sur disque.

Il est alors possible de travailler de manière avec le contenu d'un fichier ou contenu mémoire

  • Les Fichiers sur disques peuvent être des tous de types même le système Page Files
  • Les Fichiers peuvent être chargés entièrement ou découpés en bloc
  • La seule limitation est que l'on ne peut pas utiliser des fichiers se trouvant sur une autre Computer
Image non disponible

II. Avantages

Partage mémoire entre plusieurs Processus de manière à communiquer entre eux

Accès très rapide aux fichiers sur le disque

Mise a jour de DLL, etc

II-A. API Utilisée

  1. CreateFile
  2. CreateFileMapping
  3. MapiewOfFile
  4. MapViewOfFileEx
  5. OpenMappedFile
  6. UmpapViewOfFile
  7. FlushViewOfFile

Explication des Api

CreateFile : Permet de créer ou d'ouvrir les objets suivants

  1. files
  2. pipes
  3. mailslots
  4. communications resources
  5. disk devices (Windows NT only)
  6. consoles
  7. directories (open only)

CreateFileMapping : Crée un un object de mémoire partagée Nommé ou anonyme

MapiewOfFile : Mappe dans la zone mémoire du process l'object précédemment obtenu par l'appel à Create FileMapping

MapViewOfFileEx : Identique à MapiewOfFile mais avec la possibilité supplémentaire d'indiquer ou l'object. FileMapping doit être placé dans la mémoire du process appelant

OpenFileMapping : Ouvre un object FileMapping

Cette fonction est généralement utilisée pour connaître le Handle d'un object FileMapping

UmpapViewOfFile : Retire de l'espace mémoire du process l'object FileMapping

FlushViewOfFile : Permet de remplir des fichier Mappés sur dique avec la valeur 0 en précisant l'adresse de départ ainsi que le nombre d'éléments à supprimer

II-B. Programme d'exemple

Dans le but de démontrer une utilisation possible des Mapping Files, je vous propose une application

J'ai remarqué que depuis la version 3 du compilateur Borland C++ Builder la table d'exportation de l'exécutable généré est toujours emplie avec des symboles plus ou moins barbares du genre suivant

  • @@Testbitmap@Finalize
  • @@Testbitmap@Initialize
  • @Classes@TComponent@UpdateRegistry$qqr4boolx17System@AnsiStringxt2
  • @Forms@TForm@$bctr$qqrp18Classes@TComponent
  • @Forms@TForm@$bdtr$qqrv

ce qui ne donne pas une représentation très professionnelle de l'exécutable fourni les exécutable générés par Delphi ne souffrent pas de ce défaut

l'application proposée à l'utilité de supprimer la table d'exportation des exécutables générés par C++ Builder

II-C. Limitation

Ce programme est écrit en C++ à l'aide de C++ Builder 6

Dans ce programme est utilisé certaines fonctionnalités VCL qui rendent la parti GUI non portable sur une autre compilateur, l'adaptation du code est par contre possible

II-D. Cahier des Charges

  • Etablir un Tools avec un GUI
  • Permettre la possibilité d'installer et de désinstaller ce programme dans la Shell
  • Permettre le fonctionnement via une ligne de commande
  • Permettre la Commande Via la Shell (Touche droite de la souris sur un fichier Exe)
  • · Création d'une classe de travail pour les Files Mapping

III. Définition du GUI

Image non disponible

III-A. définition de la forme principale

Pour Commencer nous allons définir la forme Principale

Déposer les Composants suivants sur une Form

1 TAction List ActionList1
1 TImageList ImageList1
1 TMainMenu MainMenu1
1 TOpenDialog OpenDialog1
1 TTool Bar Align = alTop
1 TPanel Align = alClient
1 TStatusBar ""

Déposer les Composants sur le Panel

1 Tedit Edit1
1 Tbutton Button1
1 Tlabel Label1

Clicker avec la touche droite de la souris sur la tool Bar et créer 4 Boutons

TToolsButtons ToolsButtons1
TToolsButtons ToolsButtons2
TToolsButtons ToolsButtons3
TToolsButtonsl ToolsButtons4

III-B. ImageList

Nous allons créer Charger les Images dans le composant ImageList1

choisir 5 Images dans les fichiers communs de Borland

Image1 Open File
Image2 Execute
Image3 Cancel
Image4 Close
Image5 Help
Image non disponible

III-C. ActionsList

Ouvrir le composant ActionList1

Nom Caption Image OnExecute
OpenFile Open * OpenFileExecute
Execute Execute * ExecuteExecute
CancelAction Cancel * CancelActionExecute
About A propos de * AboutExecute

*= Index de l'image choisie

Image non disponible

III-D. Menu Principal

Création d'un menu selon Image Suivante

Image non disponible

donnez aux Items Actions les valeurs suivantes

Item Action
Open OpenFile
Execute Execute
Close CloseApp
A Propos de About

III-E. Tools Buttons

Donnez aux aux Actions de Buttons les Valeurs Suivantes

Item Action
ToolButton1 OpenFile
ToolButton2 Execute
CancelAction CancelAction
ToolButton6 CloseApp

Le design de l'application est maintenant terminé

IV. Classe TMMF

Pour travailler en C++ avec les API WIN32 il est préférable de déclarer une nouvelle classe

IV-A. But de cette classe

  • Encapsuler les Api relatives aux Files Mapping
  • Fournir via l'appel a une méthode public un pointeur sur une zone mappée
  • Dans le cas d'une erreur fournir un message d'erreur win32

IV-B. Déclaration de la classe

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
#ifndef MMFH
#define MMFH
#include <vcl.h>
//---------------------------------------------------------------------------
class TMMF {
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; private :
&#160;&#160;&#160; &#160;&#160;&#160; HANDLE FFileMap;
&#160;&#160;&#160; &#160;&#160;&#160; HANDLE FFileHandle;
&#160;&#160;&#160; &#160;&#160;&#160; void * FMappingPtr;
&#160;&#160;&#160; &#160;&#160;&#160; DWORD FFileSize;
&#160;&#160;&#160; &#160;&#160;&#160; DWORD FFileSizeHigh;
&#160;&#160;&#160; &#160;&#160;&#160; AnsiString FFileName;
&#160;&#160;&#160; &#160;&#160;&#160; AnsiString FErrorMsg;
&#160;&#160;&#160; &#160;&#160;&#160; void __fastcall GetFile();
&#160;&#160;&#160; &#160;&#160;&#160; void __fastcall GetMapping();
&#160;&#160;&#160; &#160;&#160;&#160; void __fastcall GetPtrAdresse();
&#160;&#160;&#160; &#160;&#160;&#160; void __fastcall GetSizeofFile();
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; protected :
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; public :
&#160;&#160;&#160; &#160;&#160;&#160; __fastcall TMMF();
&#160;&#160;&#160; &#160;&#160;&#160; __fastcall TMMF(AnsiString FileName);
&#160;&#160;&#160; &#160;&#160;&#160; __fastcall ~TMMF();
&#160;&#160;&#160; &#160;&#160;&#160; bool __fastcall Execute();
&#160;&#160;&#160; &#160;&#160;&#160; __property HANDLE FileHandle = { read = FFileHandle };
&#160;&#160;&#160; &#160;&#160;&#160; __property HANDLE MappingHandle = { read = FFileMap };
&#160;&#160;&#160; &#160;&#160;&#160; __property void * PtrMapping = { read = FMappingPtr };
&#160;&#160;&#160; &#160;&#160;&#160; __property AnsiString ErrorMessage = { read = FErrorMsg };
&#160;&#160;&#160; &#160;&#160;&#160; __property DWORD FileSize = { read = FFileSize };
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

définitions des champs

Champs description
HANDLE FFileMap Contient le Handle du fichier Ouvert
HANDLE FFileHandle Contient le Nom du Fichier
void* FMappingPtr Contient le pointeur sur la zone mappée
DWORD FFileSize Contient la taille du fichier mappé
DWORD FFileSizeHigh Contient la taille haute du fichier mappé
AnsiString FFileName Contient le nom du fichier à mappé
AnsiString FErrorMsg Contient le message d'erreur

définitions des méthodes

Méthode partie description
__fastcall TMMF() public Constructeur par défault
__fastcall TMMF(AnsiString FileName) public Constructeur avec nom du fichier
__fastcall ~TMMF(); public destructeur
bool __fastcall Execute() public appel des différentes fonctions
void __fastcall GetFile() private initialise FfileHandle
void __fastcall GetPtrAdresse() private initialise FMappingPtr
void __fastcall GetSizeofFile() private initialise FfileSize et FfileSizeHigh

IV-C. Implémentation de la classe

Constructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
#include "MMF.h"
//---------------------------------------------------------------------------
__fastcall TMMF::TMMF()
&#160;&#160;&#160; :FFileMap(NULL),
&#160;&#160;&#160; FFileHandle(NULL),
&#160;&#160;&#160; FMappingPtr(NULL),
&#160;&#160;&#160; FFileSize(0),
&#160;&#160;&#160; FFileSizeHigh(0),
&#160;&#160;&#160; FFileName(""),
&#160;&#160;&#160; FErrorMsg("")
&#160;&#160;&#160; 
{
&#160;&#160;&#160; 
} 

IV-D. Constructeur avec FileName

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
//---------------------------------------------------------------------------
__fastcall TMMF::TMMF(AnsiString FileName) 
&#160;&#160;&#160; :FFileMap(NULL),
&#160;&#160;&#160; FFileHandle(NULL),
&#160;&#160;&#160; FMappingPtr(NULL),
&#160;&#160;&#160; FFileSize(0),
&#160;&#160;&#160; FFileSizeHigh(0),
&#160;&#160;&#160; FFileName(""),
&#160;&#160;&#160; FErrorMsg("")
&#160;&#160;&#160; 
{
&#160;&#160;&#160; FFileName=FileName;
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

IV-E. Destructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
__fastcall TMMF::~TMMF()
{
&#160;&#160;&#160; if (FMappingPtr)
&#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; UnmapViewOfFile(FMappingPtr);
&#160;&#160;&#160; &#160;&#160;&#160; FMappingPtr=NULL;
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; if (FFileMap)
&#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; CloseHandle(FFileMap);
&#160;&#160;&#160; &#160;&#160;&#160; FFileMap=NULL;
&#160;&#160;&#160; &#160;&#160;&#160; } 
&#160;&#160;&#160; if (FFileHandle)
&#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; CloseHandle(FFileHandle);
&#160;&#160;&#160; &#160;&#160;&#160; FFileHandle=NULL;
&#160;&#160;&#160; &#160;&#160;&#160; } 
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

IV-F. Méthode GetFile

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
void __fastcall TMMF::GetFile()
{
&#160;&#160;&#160; FFileHandle=CreateFile(FFileName.c_str(), // pointer to name of the file
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; GENERIC_READ|GENERIC_WRITE, // access (read-write) mode
&#160;&#160;&#160; &#160;&#160;&#160; FILE_SHARE_READ|FILE_SHARE_WRITE,// share mode
&#160;&#160;&#160; &#160;&#160;&#160; NULL, // pointer to security attributes
&#160;&#160;&#160; &#160;&#160;&#160; OPEN_EXISTING, // how to create
&#160;&#160;&#160; &#160;&#160;&#160; FILE_ATTRIBUTE_NORMAL, // file attributes
&#160;&#160;&#160; &#160;&#160;&#160; NULL); //TODO: Add your source code here
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; if (FFileHandle==NULL |(long )FFileHandle==-1)
&#160;&#160;&#160; RaiseLastOSError();
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

IV-G. Méthode GetMapping

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
void __fastcall TMMF::GetMapping()
{
&#160;&#160;&#160; FFileMap=CreateFileMapping(FFileHandle, // handle to file to map
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; NULL, // optional security attributes
&#160;&#160;&#160; &#160;&#160;&#160; PAGE_READWRITE, // protection for mapping object
&#160;&#160;&#160; &#160;&#160;&#160; 0, // high-order 32 bits of object size
&#160;&#160;&#160; &#160;&#160;&#160; 0, // low-order 32 bits of object size
&#160;&#160;&#160; &#160;&#160;&#160; NULL); //
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; if (!FFileMap)
&#160;&#160;&#160; RaiseLastOSError();
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

IV-H. Méthode GetPtrAdresse

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
void __fastcall TMMF::GetPtrAdresse()
{
&#160;&#160;&#160; FMappingPtr=MapViewOfFile(FFileMap,
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; FILE_MAP_ALL_ACCESS,
&#160;&#160;&#160; &#160;&#160;&#160; 0,
&#160;&#160;&#160; &#160;&#160;&#160; 0,
&#160;&#160;&#160; &#160;&#160;&#160; 0);
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; if (!FMappingPtr)
&#160;&#160;&#160; RaiseLastOSError();
&#160;&#160;&#160; 
} 

IV-I. Méthode Execute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
bool __fastcall TMMF::Execute()
{
&#160;&#160;&#160; try 
&#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; GetFile();
&#160;&#160;&#160; &#160;&#160;&#160; GetMapping();
&#160;&#160;&#160; &#160;&#160;&#160; GetPtrAdresse();
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; catch (EOSError &E)
&#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; FErrorMsg=E.Message;
&#160;&#160;&#160; &#160;&#160;&#160; return false;
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; GetSizeofFile();
&#160;&#160;&#160; return true;
&#160;&#160;&#160; 
} 

IV-J. Méthode GetSizeofFile

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TMMF::GetSizeofFile()
{
&#160;&#160;&#160; FFileSize=GetFileSize(FFileHandle,&FFileSizeHigh); 
} 

IV-K. Explicatif

Généralement les APIwin32 retourne un code indiquant si l'opération désirée s'est terminée par un succès :

  • Une valeur de 0 ou true indique une opération terminée avec succès
  • Dans le cas contraire un appel GetLastError() nous retourne le code d'erreur

La VCL intègre une classe EOSError permettant de retourner dans la variable membre Message le code ainsi que le message d'erreur

Il suffit donc de tester la sortie de l'api et en cas d'insuccès de générer une exception De type EOSError par un appel à RaiseLastOSError()

La classe d'exception EOSError est intégrée dans C++ builder 6 dans les versions précédentes

On peut utiliser la classe d'exception EWin32Error et pour le déclenchement d'une exception de ce type l'appel à RaiseLastWin32Error()

IV-L. Description des méthodes

IV-L-1. Le constructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
__fastcall TMMF::TMMF(AnsiString FileName)
&#160;&#160;&#160; :FFileMap(NULL),
&#160;&#160;&#160; FFileHandle(NULL),
&#160;&#160;&#160; FMappingPtr(NULL),
&#160;&#160;&#160; FFileSize(0),
&#160;&#160;&#160; FFileSizeHigh(0),
&#160;&#160;&#160; FFileName(""),
&#160;&#160;&#160; FErrorMsg("")
&#160;&#160;&#160; 
{
&#160;&#160;&#160; FFileName=FileName;
&#160;&#160;&#160; 
} } 

initialise les membres de la classe puis copie dans FFileName le paramètre du constructeur

IV-L-2. le Destructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
__fastcall TMMF::~TMMF()
{
&#160;&#160;&#160; if (FMappingPtr)
&#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; UnmapViewOfFile(FMappingPtr);
&#160;&#160;&#160; &#160;&#160;&#160; FMappingPtr=NULL;
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; if (FFileMap)
&#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; CloseHandle(FFileMap);
&#160;&#160;&#160; &#160;&#160;&#160; FFileMap=NULL;
&#160;&#160;&#160; &#160;&#160;&#160; } 
&#160;&#160;&#160; if (FFileHandle)
&#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; CloseHandle(FFileHandle);
&#160;&#160;&#160; &#160;&#160;&#160; FFileHandle=NULL;
&#160;&#160;&#160; &#160;&#160;&#160; } 
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

teste l'état des différents pointeurs , libére la zone mappée ainsi que les handles de fichiers

IV-L-3. méthode GetFile()

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
void __fastcall TMMF::GetFile()
{
&#160;&#160;&#160; FFileHandle=CreateFile(FFileName.c_str(), // pointer to name of the file
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; GENERIC_READ|GENERIC_WRITE, // access (read-write) mode
&#160;&#160;&#160; &#160;&#160;&#160; FILE_SHARE_READ|FILE_SHARE_WRITE,// share mode
&#160;&#160;&#160; &#160;&#160;&#160; NULL, // pointer to security attributes
&#160;&#160;&#160; &#160;&#160;&#160; OPEN_EXISTING, // how to create
&#160;&#160;&#160; &#160;&#160;&#160; FILE_ATTRIBUTE_NORMAL, // file attributes
&#160;&#160;&#160; &#160;&#160;&#160; NULL); //TODO: Add your source code here
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; if (FFileHandle==NULL |(long )FFileHandle==-1)
&#160;&#160;&#160; RaiseLastOSError();
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

cette méthode utilise l'API WIN32 CreateFile pour obtenir un Handle de fichier
le champ FFileHandle contient le Handle du fichier
si la valeur de retour est différente d'un Handle Valide on génère une exception

IV-L-4. méthode GetMapping

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
void __fastcall TMMF::GetMapping()
{
&#160;&#160;&#160; FFileMap=CreateFileMapping(FFileHandle, // handle to file to map
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; NULL, // optional security attributes
&#160;&#160;&#160; &#160;&#160;&#160; PAGE_READWRITE, // protection for mapping object
&#160;&#160;&#160; &#160;&#160;&#160; 0, // high-order 32 bits of object size
&#160;&#160;&#160; &#160;&#160;&#160; 0, // low-order 32 bits of object size
&#160;&#160;&#160; &#160;&#160;&#160; NULL); //
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; if (!FFileMap)
&#160;&#160;&#160; RaiseLastOSError();
&#160;&#160;&#160; 
} //---------------------------------------------------------------------------

cette méthode utilise l'API WIN32 CreateFileMapping pour créer une zone commune en mémoire et retourner dans le le champ FFileMap un Handle sur cette zone si la valeur de retour est NULL on génère une exception

IV-L-5. méthode GetPtrAdresse

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
void __fastcall TMMF::GetPtrAdresse()
{
&#160;&#160;&#160; FMappingPtr=MapViewOfFile(FFileMap,
&#160;&#160;&#160; 
&#160;&#160;&#160; &#160;&#160;&#160; FILE_MAP_ALL_ACCESS,
&#160;&#160;&#160; &#160;&#160;&#160; 0,
&#160;&#160;&#160; &#160;&#160;&#160; 0,
&#160;&#160;&#160; &#160;&#160;&#160; 0);
&#160;&#160;&#160; &#160;&#160;&#160; 
&#160;&#160;&#160; if (!FMappingPtr)
&#160;&#160;&#160; RaiseLastOSError();
&#160;&#160;&#160; 
} 

cette méthode utilise l'API WIN32 MapViewofFile qui retourne dans FmappingPtr un pointeur sur la zone mappée en mémoire avec FFileMap en paramètre si la valeur de retour est NULL on génère une exception

IV-L-6. méthode GetSizeofFile

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TMMF::GetSizeofFile()
{
&#160;&#160;&#160; FFileSize=GetFileSize(FFileHandle,&FFileSizeHigh);
&#160;&#160;&#160; }

cette méthode initialise les 2 champs membres FFileSize et FFileSizeHigh avec la longueur du fichier obtenu par l'appel à GetFileSize

IV-L-7. méthode Execute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
bool __fastcall TMMF::Execute()
{
&#160;&#160;&#160; try 
&#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; GetFile();
&#160;&#160;&#160; &#160;&#160;&#160; GetMapping();
&#160;&#160;&#160; &#160;&#160;&#160; GetPtrAdresse();
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; catch (EOSError &E)
&#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; FErrorMsg=E.Message;
&#160;&#160;&#160; &#160;&#160;&#160; return false;
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; GetSizeofFile();
&#160;&#160;&#160; return true;
&#160;&#160;&#160; 
}

la méthode Execute est le cœur de cette classe , elle appelle successivement dans une partie protégée du programme (try catch) GetFile,GetMapping,GetPtrAdresse en cas d'erreur dans une de ces méthodes la variable FerrorMessage est initialisée avec le message d'erreur retournée par le système d'exploitation

V. Classe Tform

Déclaration de la classe

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
//---------------------------------------------------------------------------
#ifndef mainH
#define mainH
//---------------------------------------------------------------------------
#include lt;Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Dialogs.hpp>
#include <ActnList.hpp>
#include <ComCtrls.hpp>
#include <ExtCtrls.hpp>
#include <ImgList.hpp>
#include <Menus.hpp>
#include <ToolWin.hpp>
#define ExeKeyName "exefile\\shell"
#define CommandKeyName "ExportCleaner\\Command"
#define PrgKeyName "ExportCleaner"
#define Command "ExportCleaner.exe %1"
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
&#160;&#160;&#160; __published: // Composants gérés par l'EDI
&#160;&#160;&#160; TPanel *Panel1;
&#160;&#160;&#160; TToolBar *ToolBar1;
&#160;&#160;&#160; TOpenDialog *OpenDialog1;
&#160;&#160;&#160; TMainMenu *MainMenu1;
&#160;&#160;&#160; TImageList *ImageList1;
&#160;&#160;&#160; TActionList *ActionList1;
&#160;&#160;&#160; TAction *OpenFile;
&#160;&#160;&#160; TAction *Execute;
&#160;&#160;&#160; TAction *CloseApp;
&#160;&#160;&#160; TEdit *Edit1;
&#160;&#160;&#160; TButton *Button1;
&#160;&#160;&#160; TLabel *Label1;
&#160;&#160;&#160; TMenuItem *Open1;
&#160;&#160;&#160; TMenuItem *Execute1;
&#160;&#160;&#160; TMenuItem *Open2;
&#160;&#160;&#160; TMenuItem *Close1;
&#160;&#160;&#160; TMenuItem *N3;
&#160;&#160;&#160; TAction *CancelAction;
&#160;&#160;&#160; TStatusBar *StatusBar1;
&#160;&#160;&#160; TToolButton *ToolButton1;
&#160;&#160;&#160; TToolButton *ToolButton2;
&#160;&#160;&#160; TToolButton *ToolButton5;
&#160;&#160;&#160; TToolButton *ToolButton6;
&#160;&#160;&#160; TMenuItem *Aide;
&#160;&#160;&#160; TAction *About;
&#160;&#160;&#160; TMenuItem *AProposde1;
&#160;&#160;&#160; void __fastcall OpenFileExecute(TObject *Sender);
&#160;&#160;&#160; void __fastcall CloseAppExecute(TObject *Sender);
&#160;&#160;&#160; void __fastcall ExecuteExecute(TObject *Sender);
&#160;&#160;&#160; void __fastcall CancelActionExecute(TObject *Sender);
&#160;&#160;&#160; void __fastcall FormDestroy(TObject *Sender);
&#160;&#160;&#160; void __fastcall AboutExecute(TObject *Sender);
&#160;&#160;&#160; private :
&#160;&#160;&#160; AnsiString FileName; // Déclarations de l'utilisateur
&#160;&#160;&#160; void * DirectoryEntry;
&#160;&#160;&#160; void __fastcall CleanPtr();
&#160;&#160;&#160; void __fastcall ParseCmdLine();
&#160;&#160;&#160; public : // Déclarations de l'utilisateur
&#160;&#160;&#160; __fastcall TForm1(TComponent* Owner);
&#160;&#160;&#160; 
} ;
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif

nous allons déclarer dans la partie private de la classe TForm1 les champs Suivants :

 
Sélectionnez
1.
2.
AnsiString FileName; // Déclarations de l'utilisateur
void* DirectoryEntry;

les Méthodes suivantes :

 
Sélectionnez
1.
2.
void__fastcall CleanPtr();
void__fastcall ParseCmdLine();

description des champs :

  • FileName est utilisé pour stocker le nom de l'exécutable à traiter
  • DirectoryEntry est un pointeur sur la directoy entry de l'exécutable

V-A. Constructeur

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
__fastcall TForm1::TForm1(TComponent* Owner)
&#160;&#160;&#160; : TForm(Owner)
&#160;&#160;&#160; 
{
&#160;&#160;&#160; pMap=NULL;
&#160;&#160;&#160; CleanPtr();
&#160;&#160;&#160; StatusBar1->SimpleText="Please Select exe File";
&#160;&#160;&#160; if (ParamCount()>=1)
&#160;&#160;&#160; 
&#160;&#160;&#160; ParseCmdLine(); // appel avec une ligne de commande
&#160;&#160;&#160; }

on appelle un méthode pour s'assurer que les pointeurs sont dans un état défini, et que les hanlde de fichiers sont tous libéré l'appel à la méthode ParseCmdLine permet de controler si une ligne de commande est présente

V-B. Méthode OpenFileExecute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
void __fastcall TForm1::OpenFileExecute(TObject *Sender)
{ 
&#160;&#160;&#160; if (OpenDialog1->Execute())
&#160;&#160;&#160; {
&#160;&#160;&#160; &#160;&#160;&#160; FileName=OpenDialog1->FileName;
&#160;&#160;&#160; &#160;&#160;&#160; Edit1->Text= FileName;
&#160;&#160;&#160; &#160;&#160;&#160; StatusBar1->SimpleText="Please Press Execute";
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; Execute->Enabled = (FileName!="");
&#160;&#160;&#160; }

cette méthode appelée depuis le menu ou un Tools Button affiche une DialogBox Standard qui permet la saisie de l'exécutable à traiter

V-C. Méthode CloseApp

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TForm1::CloseAppExecute(TObject *Sender)
{ 
&#160;&#160;&#160; Close();
&#160;&#160;&#160; }

Appelle la fermeture du programme

V-D. Méthode ExecuteExecute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
void __fastcall TForm1::ExecuteExecute(TObject *Sender)
{ 
&#160;&#160;&#160; ULONG DSize;
&#160;&#160;&#160; IMAGE_NT_HEADERS * myImage;
&#160;&#160;&#160; DWORD HeaderSum,CheckSum ;
&#160;&#160;&#160; TMMF * myMMF = new TMMF(FileName);
&#160;&#160;&#160; Execute->Enabled=false;
&#160;&#160;&#160; OpenFile->Enabled=false;
&#160;&#160;&#160; if (myMMF->Execute())
&#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; try 
&#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; DirectoryEntry=ImageDirectoryEntryToData(myMMF->PtrMapping,
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; false,
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; IMAGE_DIRECTORY_ENTRY_EXPORT,
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &DSize );
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; if (!DirectoryEntry)
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; RaiseLastOSError();
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; FlushViewOfFile(DirectoryEntry,DSize);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; myImage= CheckSumMappedFile(myMMF->PtrMapping,
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; myMMF->FileSize,
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &HeaderSum,
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &CheckSum);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; myImage->OptionalHeader.DataDirectory[0].VirtualAddress=0L;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; myImage->OptionalHeader.DataDirectory[0].Size=0L;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; catch (EOSError &E)
&#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; StatusBar1->SimpleText="Exe File Contains no Export Directories";
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; MessageDlg(StatusBar1->SimpleText,mtInformation,TMsgDlgButtons()<< mbOK, 0);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; delete myMMF;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; CleanPtr();
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; OpenFile->Enabled=true;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; return ;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; } 
&#160;&#160;&#160; &#160;&#160;&#160; StatusBar1->SimpleText="Saved Successfuly ..." ;
&#160;&#160;&#160; &#160;&#160;&#160; MessageDlg(StatusBar1->SimpleText,mtInformation, TMsgDlgButtons()<< mbOK, 0);
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; else 
&#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; MessageDlg(myMMF->ErrorMessage, mtError, TMsgDlgButtons() << mbOK, 0);
&#160;&#160;&#160; &#160;&#160;&#160; StatusBar1->SimpleText="Error occurs ....";
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; delete myMMF;
&#160;&#160;&#160; CleanPtr();
&#160;&#160;&#160; OpenFile->Enabled=true;
&#160;&#160;&#160; }

cette méthode est le cœur du programme

 
Sélectionnez
1.
&#160;&#160;&#160; IMAGE_NT_HEADERS * myImage; DWORD HeaderSum,CheckSum ; ULONG DSize;

MyImage est un pointeur sur la structure IMAGE_NT_HEADERS qui contient la Strucuture du fichier dans le monde Windows PE32 HeaderSum,CheckSum,Dsize sont des variables de Travail

 
Sélectionnez
1.
&#160;&#160;&#160; TMMF * myMMF = new TMMF(FileName); MyMMF contient une instance de la classe TMMF 

L'appel à la méthode Execute va nous retourner un pointeur sur la zone mappée

Dans un bloc protégé on va tenter d'obtenir dans DirectoryEntry un pointeur sur la table d'exportation de l'executable par un appel a l'API WIN32 ImageDirectoryEntryToData En cas de retour avec une valeur NULL une execption est déclenchée

Cette exeption est interceptée dans le Bloc Catch qui affiche une boîte de dialogue Affiche une message dans la ligne de Status, détruit le myMMF,et sort de la méthode

si tout c'est bien passé Il nous reste maintenant à supprimer cette table d'exportation à l'aide FlushViewOfFile(DirectoryEntry,DSize);

Nous devons maintenant ajuster l'entête PE de notre exécutable à une valeur correcte

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
myImage= CheckSumMappedFile(

&#160;&#160;&#160; pMap,
&#160;&#160;&#160; FielSize,
&#160;&#160;&#160; &HeaderSum,
&#160;&#160;&#160; &CheckSum);
&#160;&#160;&#160; myImage->OptionalHeader.DataDirectory[0].VirtualAddress=0L;
&#160;&#160;&#160; myImage->OptionalHeader.DataDirectory[0].Size=0L;
&#160;&#160;&#160; 

l'Api CheckSumMappedFile nous renvoie un pointeur sur IMAGE_NT_HEADERS, ainsi que la taille du Header et son check Summ on positionne à la taille à 0

 
Sélectionnez
1.
2.
3.
&#160;&#160;&#160; myImage->OptionalHeader.DataDirectory[0].VirtualAddress=0L;
&#160;&#160;&#160; myImage->OptionalHeader.DataDirectory[0].Size=0L;
&#160;&#160;&#160; 

On affiche le résultat des operations dans la StatusBar ,ainsi que dans une boite de dialogue , détruit le myMMF,et sort de la méthode

V-E. Méthode CleanPtr

 
Sélectionnez
1.
2.
3.
4.
5.
6.
void __fastcall TForm1::CleanPtr()
{ 
&#160;&#160;&#160; DirectoryEntry=NULL;
&#160;&#160;&#160; FileName=NULL;
&#160;&#160;&#160; Edit1->Text="";
&#160;&#160;&#160; }

la méthode CleanPtr réinitialise les variables,ainsi que le champ Edit1->Text

V-F. Méthode CancelActionExecute

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
void __fastcall TForm1::CancelActionExecute(TObject *Sender)
{ 
&#160;&#160;&#160; OpenFile->Enabled=true;
&#160;&#160;&#160; Execute->Enabled=false;
&#160;&#160;&#160; CleanPtr();
&#160;&#160;&#160; StatusBar1->SimpleText="Please Select exe File";
&#160;&#160;&#160; }

Cancel annule les ordres en cours , appelle cleanPtr, et remet le système dans son état de départ

V-G. Méthode FormDestroy

 
Sélectionnez
1.
2.
3.
4.
void __fastcall TForm1::FormDestroy(TObject *Sender)
{ 
&#160;&#160;&#160; CleanPtr();
&#160;&#160;&#160; }

Form Destroy Appelé par Close() libére la mémoire

V-H. Méthode ParseCmdLine

 
Sélectionnez
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
void __fastcall TForm1::ParseCmdLine() { 
&#160;&#160;&#160; AnsiString Tmp;
&#160;&#160;&#160; int ParamNr=ParamCount();
&#160;&#160;&#160; if (ParamNr ==1) // Command Line Exists
&#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; AnsiString cmd=ParamStr(1).UpperCase();
&#160;&#160;&#160; &#160;&#160;&#160; if ((cmd =="/INSTALL") ||(cmd =="/UNINSTALL"))
&#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; TRegistry* mReg= new TRegistry();
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; try 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; mReg->RootKey=HKEY_CLASSES_ROOT;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; mReg->OpenKey(ExeKeyName,false); // open Shell Key in registry
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; if (cmd =="/INSTALL")
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }{
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; if (!mReg->KeyExists(PrgKeyName))
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; mReg->OpenKey(CommandKeyName,true); // Command Install
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; mReg->WriteString("",Command);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; MessageDlg("Export Cleaner installed Succesfuly", mtInformation, TMsgDlgButtons() << mbOK, 0);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; } if (cmd =="/UNINSTALL")
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; if (mReg->KeyExists(PrgKeyName))
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; mReg->DeleteKey(PrgKeyName); // delete Registry Key
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; MessageDlg("Export Cleaner desinstalled Succesfuly", mtInformation, TMsgDlgButtons() << mbOK, 0);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; catch (...)
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; mReg->CloseKey();
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; delete mReg;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; Application->Terminate(); // Exit Application
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; else 
&#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; for (int i=0;i<ParamNr;i++)
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; { 
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; Tmp+=ParamStr(i+1);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; Tmp+=" ";
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; Tmp.Delete(Tmp.Length(),1); //delete Last Space
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; FileName=Tmp;
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; if ((!FileExists(Tmp)) &&(ExtractFileExt(Tmp)!=".exe")
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; ) MessageBox(Application->Handle,
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; "File Not Exist or Not a valid Exe File",
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; "Export Cleaner",
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; MB_OK|MB_ICONINFORMATION);
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; else ExecuteExecute(NULL); // Call suppress
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; Application->Terminate(); // Exit Application
&#160;&#160;&#160; &#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; &#160;&#160;&#160; }
&#160;&#160;&#160; }

cette méthode teste la présence d'une ligne de commande si la ligne de commande est égale à INSTALL le programme installe dans la registry un shell pour les fichiers de type exe ce qui permettra avec un click bouton droit de la souris la possibilité de lancer le programme exportCLeaner.exe

une boite de dialogue vous indique le résultat de l'opération

La ligne de commande avec un une valeur egale à /UNINSTALL supprimera de la registry la shell pour les fichiers de type exe

si une ligne de commande est présente et n'est pas égale aux commdes d'installation cela signifie que le paramètre est le nom du fichier exe à traiter on test s'il s'agit bien d'un fichier executable et si la réponse est positive on lance l'application

VI. Installation dans C++ Builder

  • dans le menu Outils sélectionner Configurer les outils
  • sélectionner ajouter
  • Dans le champ Titre insérer ExportCLeaner
  • sélectionner le bouton Parcourir et sélectionner le fichier ExportCleaner.exe
  • sélectionner le bouton Macro dans la listBox choisisser $TDW
  • sélectionner le bouton Insérer
  • sélectionner le bouton OK

ExportCleaner est désormais installé et apparait dans la liste d'outils

VII. Utilisation dans C++ Builder

  • Compiler un nouveau projet
  • sélectionner dans le menu Outil l'item ExportCleaaner
  • a la fin de l'excution du programme une boite de dialogue vous indique le résultat de l'opération

Voir également mes autres articles :

  • Utilisation des Files Mapping sous C++Builder C++ Builder
  • La technique des PatchFiles C++ Builder
  • Maîtrisez les files d'impression sous windows C++ Builder
  • Travailler avec les Interfaces en C++Builder Partie 1 C++ Builder
  • Composant de gestion des ports d'imprimantes C++ Builder
  • Programme de Test Version ActiveX du composant TDLIoport Delphi

Sans oublier :

Vous avez aimé ce tutoriel ? Alors partagez-le en cliquant sur les boutons suivants : Viadeo Twitter Facebook Share on Google+   

Voir également mes autres articles :
Utilisation des Files Mapping sous C++Builder C++ Builder
La technique des PatchFiles C++ Builder
Maîtrisez les files d'impression sous windows C++ Builder
Composant de gestion des ports d'imprimantes C++ Builder
Programme de Test Version ActiveX du composant TDLIoport Delphi
Sans oublier :
la FAQ C++ Builder par Geronimo
la FAQ C
la FAQ C++

  

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2013 DjmSoftware. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents, images, etc. sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.