Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

Vous n'avez pas encore de compte Developpez.com ? L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Developpez.com

C++

Choisissez la catégorie, puis la rubrique :

logo
Sommaire > Interface > Ressources
        Comment créer/modifier une ressource de l'exécutable ?
        Comment lire un fichier de ressources ?
        Comment enregistrer un fichier en ressource, quelle que soit son extension ?



Comment créer/modifier une ressource de l'exécutable ?
Créé le 06/12/2006[haut]
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;

//move running application
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;

//récupération du fichier à ajouter en ressource
HANDLE hFile = CreateFile(Chemin_Fichier_Text.c_str(),
                                  GENERIC_READ,
                                  0,
                                  NULL,
                                  OPEN_EXISTING, 
                                  FILE_ATTRIBUTE_NORMAL,
                                  NULL);

if(INVALID_HANDLE_VALUE != hFile)
{
//chargement du fichier dans un buffer pour le transmettre
dwFileSize = GetFileSize(hFile, NULL);
lpBuffer = new BYTE[dwFileSize];
if(ReadFile(hFile,
lpBuffer,
dwFileSize,
&dwBytesRead,
NULL) != FALSE)
{
//récupération du Handle de la ressource
HANDLE hResource = BeginUpdateResource(OriginalPath.c_str(), FALSE);
if(NULL != hResource)
{
//mise à jour
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 : faq Comment lire un fichier de ressources ?
lien : en API Windows permettant la mise à jour de la ressource
lien : en Site donnant la méthode pour la récupération des droits d'accès

Comment lire un fichier de ressources ?
Créé le 06/12/2006[haut]
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 : faq Comment créer/modifier une ressource de l'exécutable ?

Comment enregistrer un fichier en ressource, quelle que soit son extension ?
Créé le 10/12/2007[haut]
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;
 
//procédure de sauvegarde
  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)
  {
        //chargement de la ressource
        TResourceStream *Res=new TResourceStream((int)HInstance,"IMAGEBMP",RT_RCDATA);
        TMemoryStream *image = new TMemoryStream();
        //conversion de la ressource en TMemoryStream pour retrouver le même format enregistré
        Res->SaveToStream(image);
        image->Position = 0;
        //sauvegarde de l'image dans un fichier pour la recharger plus facilement
        image->SaveToFile("image1.bmp");
        //supression de l'image et des variables
        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.


Valid XHTML 1.0 TransitionalValid CSS!

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 © 2009 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site ni de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Contacter le responsable de la rubrique C++

Partenaire : Hébergement Web