| auteur : Bandit Boy |
Les fichiers exécutables contiennent tous un fichier ressource, visible avec un explorateur de ressources (type RESEXPLORER). Ce fichier contient les données utiles à l'exécutable, comme par exemple son icône.
Il est possible d'ajouter ou de modifier cette ressource pour inclure des fichiers que l'on ne souhaite pas "voir traîner", par exemple contenant des mots de passe.
Dans un premier temps, l'exécutable étant en cours, nous n'avons pas les droits d'accès. Il est nécessaire de les obtenir pour mettre à jour l'application. Pour cela, nous allons effectuer une copie de l'exécutable au même endroit que celui en cours (donc transparent pour l'utilisateur). L'original en exécution sera au préalable déplacé dans le dossier temporaire, puis supprimé.
AnsiString TempPath;
AnsiString NewPath;
AnsiString OriginalPath;
GetTempPath (200 ,TempPath.c_str ());
GetTempFileName (TempPath.c_str (), _T (" TMP " ),0 ,NewPath.c_str ());
OriginalPath = Application- > ExeName;
if (MoveFileEx (OriginalPath.c_str (),NewPath.c_str (),MOVEFILE_REPLACE_EXISTING) = = FALSE)
ShowMessage (" Moving file error " );
if (CopyFile (NewPath.c_str (),OriginalPath.c_str (),FALSE) = = FALSE)
ShowMessage (" Copying file error " );
if (MoveFileEx (NewPath.c_str (),NULL ,MOVEFILE_DELAY_UNTIL_REBOOT) = = FALSE)
ShowMessage (" Moving file error " );
|
Comme il n'est pas possible à l'exécutable de se supprimer lui-même, il sera supprimé au redémarrage du PC par la fonction MoveFileEx en donnant le message MOVEFILE_DELAY_UNTIL_REBOOT.
Une fois les droits acquis, il n'y a plus qu'à charger le fichier à mettre en ressource puis de mettre à jour.
DWORD dwFileSize, dwBytesRead,dwBytesWritten;
LPBYTE lpBuffer;
HANDLE hFile = CreateFile (Chemin_Fichier_Text.c_str (),
GENERIC_READ,
0 ,
NULL ,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL );
if (INVALID_HANDLE_VALUE ! = hFile)
{
dwFileSize = GetFileSize (hFile, NULL );
lpBuffer = new BYTE[dwFileSize];
if (ReadFile (hFile,
lpBuffer,
dwFileSize,
& dwBytesRead,
NULL ) ! = FALSE)
{
HANDLE hResource = BeginUpdateResource (OriginalPath.c_str (), FALSE);
if (NULL ! = hResource)
{
if (UpdateResource (hResource,
RT_RCDATA,
" RESOURCEADDED " ,
MAKELANGID (LANG_NEUTRAL,SUBLANG_NEUTRAL),
(LPVOID) lpBuffer,
dwFileSize) ! = FALSE)
{
if (EndUpdateResource (hResource, FALSE) ! = FALSE)
ShowMessage (" Update succed! Please restart application " );
else
ShowMessage (" Error " + IntToStr (GetLastError ()));
}
}
}
delete [] lpBuffer;
CloseHandle (hFile);
}
|
Le fichier mis à jour se trouvant sur la copie, il faut donc relancer l'application pour voir l'effet de cette mise à jour. Ici le fichier ajouté (ou modifié s'il existe déjà sous le même nom RESOURCEADDED) est de type RCDATA.
|
lien : Comment lire un fichier de ressources ?
lien : API Windows permettant la mise à jour de la ressource
lien : Site donnant la méthode pour la récupération des droits d'accès
|
| auteur : Interruption13h |
Il suffit d'utiliser les classes TResourceStreamet TStringList comme suit :
AnsiString Chemin_Fichier_Text= ExtractFilePath (Application- > ExeName)+ " \\file.txt " ;
TResourceStream * MRes= new TResourceStream ((int )HInstance, " RESOURCE " , RT_RCDATA);
MRes- > SaveToFile (Chemin_Fichier_Text);
TStringList * File= new TStringList;
File- > LoadFromFile (Chemin_Fichier_Text);
DeleteFile (Chemin_Fichier_Text);
|
Ici on écrit dans un fichier temporaire le contenu de la resource "RESOURCE", puis on le charge dans un TStringList pour utilisation.
|
lien : Comment créer/modifier une ressource de l'exécutable ?
|
| auteurs : Bandit Boy, pottiez |
L'idée développée est d'enregistrer un fichier (bmp, gif, csv ...) en ressource, quel que soit son type.
Il se peut que durant une application, on souhaite sauver des fichiers, des configurations ou tout autres fichiers qui ne puissent pas être pré-chargés durant la création de l'application.
Dans l'exemple suivant, on sauvegarde le fichier en ressource, l'important est de passer par le type TStream, pour le sauver en RC_DATA.
Pour l'enregistrer:
TMemoryStream * image = new TMemoryStream ();
Image1- > Picture- > Graphic- > SaveToStream (image);
image- > Position = 0 ;
AnsiString TempPath,NewPath,OriginalPath;
GetTempPath (200 ,TempPath.c_str ());
GetTempFileName (TempPath.c_str (), " TMP " ,0 ,NewPath.c_str ());
OriginalPath = Application- > ExeName;
if (MoveFileEx (OriginalPath.c_str (),NewPath.c_str (),MOVEFILE_REPLACE_EXISTING) = = FALSE)
Application- > MessageBox (" Impossible de déplacer l'exe " ," Erreur " ,MB_OK+ MB_ICONWARNING);
if (CopyFile (NewPath.c_str (),OriginalPath.c_str (),FALSE) = = FALSE)
Application- > MessageBox (" Impossible de copier l'exe " ," Erreur " ,MB_OK+ MB_ICONWARNING);
if (MoveFileEx (NewPath.c_str (),NULL ,MOVEFILE_DELAY_UNTIL_REBOOT) = = FALSE)
Application- > MessageBox (" Impossiblede déplacer la copie " ," Erreur " ,MB_OK+ MB_ICONWARNING);
DWORD dwFileSize, dwBytesRead,dwBytesWritten;
LPBYTE lpBuffer;
HANDLE hResource = BeginUpdateResource (OriginalPath.c_str (), FALSE);
if (NULL ! = hResource)
{
if (UpdateResource (hResource,RT_RCDATA," IMAGEBMP " ,MAKELANGID (LANG_NEUTRAL,SUBLANG_NEUTRAL),(LPVOID)image- > Memory, (DWORD)image- > Size) ! = FALSE)
{
if (EndUpdateResource (hResource, FALSE) = = FALSE)
ShowMessage (" Error " + IntToStr (GetLastError ()));
}
else
ShowMessage (" Error " + IntToStr (GetLastError ()));
}
delete image;
|
Pour le recharger, il suffit de lire le fichier en tant que TRessourceStream, de le convertir en TSream pour obtenir le format de sauvegarde, puis de sauver le fichier en tant que son propre type (".txt" pour les fichier texte, ".csv" pour les csv ...)
Pour le recharger :
hnd = FindResource ( NULL , " IMAGEBMP " , RT_RCDATA);
if (hnd ! = NULL )
{
TResourceStream * Res= new TResourceStream ((int )HInstance," IMAGEBMP " ,RT_RCDATA);
TMemoryStream * image = new TMemoryStream ();
Res- > SaveToStream (image);
image- > Position = 0 ;
image- > SaveToFile (" image1.bmp " );
Image1- > Picture- > Bitmap- > LoadFromFile (" image1.bmp " );
DeleteFile (" image1.bmp " );
delete Res;
delete image;
}
|
Par exemple dans une application multilangue, on peut sauver dans un fichier ini, txt ou autre les configurations (choix de la langue, fichiers chargés, modifications apportées par l'utilisateur...) puis le sauver en Ressource pour que l'exe soit portable.
L'avantage de cette manipulation est que TOUT est dans UN fichier : l'application elle-même.
L'inconvénient est que le code est un peu lourd à placer, et qu'il faut que l'application soit modifiable (non en lecture seule) pour être modifiée.
|
Consultez les autres F.A.Q.
|
|