Compago

...free knowledge

 
  • Increase font size
  • Default font size
  • Decrease font size
Home Manuali Programmazione Inglobare un file qualsiasi dentro un file exe

Inglobare un file qualsiasi dentro un file exe

E-mail Stampa PDF

Per incorporare un file di qualsiasi tipo dentro una applicazione possiamo procedere nel seguente modo:

  • Creare il file risorsa partendo dal file che vogliamo inserire
  • Inserire il file risorsa dentro il programma

dopo di che non ci rimane che creare una procedura di estrazione per poi poter utilizzare il file iniziale.

Vediamo come creare il file risorsa partendo da un file qualsiasi. In questo caso io utilizzo un file eseguibile "test.exe".

Per prima cosa occorre creare un file di testo con all'interno una sola riga:

test_dati RCDATA test.exe

la prima parola è il nome della risorsa, il secondo il tipo di risorsa che sto andando a creare, la terza parola e il nome del file che voglio inserire. Da notare che RCDATA stà ad indicare una tipologia di risorsa generica.

dopo di che possiamo salvare il file di testo appena creato, con estensione RC (ad esempio risorsa.RC) e copiamo il file da incorporare (in questo caso test.exe) nella stessa cartella e da linea di comando eseguiamo

 brcc32 risorsa.RC

in questo modo viene creato in output un file con lo stesso nome ma con estensione RES (nel nostro caso quindi risorsa.Res), tale file contiene la risorsa che vogliamo inserire nell' eseguibile (nel nostro caso test.exe)

A questo punto dobbiamo inserirlo nel nostro eseguibile Delphi: basta inserire la seguente riga

{$R Risorsa.RES}

Al momento della compilazione il file risorsa e quindi il file test.exe verrà incluso nell'eseguibile che stiamo complilando.

Per poi utilizzarlo dovremo estrarlo, accedendo alle stesse risorse del programma. Questo è possibile farlo utilizzando una semplice procedura:

procedure estrazione;
var
  ResStream : TResourceStream;
  FileStream : TFileStream;
  NomeOutputfile:string;
begin
  //imposto il nome del file da estrarre
  NomeOutputfile := ExtractFileDir(Paramstr(0))+'\output_test.exe';
  //prelevo la risorsa inglobata nello stesso file exe
  ResStream := TResourceStream.Create(HInstance,'test_dati',RT_RCDATA);
  try
    //creo il file di output
    FileStream := TFileStream.Create(NomeOutputfile, fmCreate);
    try
      //ci copio dentro la risorsa
      FileStream.CopyFrom(ResStream, 0);
    finally
      FileStream.Free;
    end;
  finally
    ResStream.Free;
  end;
end;

Dato che si tratta di un file eseguibile potremo mandarlo in esecuzione subito dopo l'estrazione col comando

ShellExecute(Handle,'open', pchar(NomeOutputfile),nil, nil, SW_SHOWNORMAL) ;

La tecnica precedentemente descritta la trovate nel file allegato Inglobare_un_file.zip, mentre nel file rcdatademo.zip troverete un modo differente per creare il file risorse.

In breve il file di risorse che vogliamo creare avrà:

  • un header che introduce il file
  • un header che introduce i dati (RCDATA) da inserire
  • il file dati da inserire
  • alcuni bit di riempimento così che le successive risorse da inserire inizino al limite di una DWORD.

Diciamo anche che a differenza di prima è molto più semplice creare una risorsa identificata da un numero (es. 100) che da uan stringa (es. MIA_RISORSA), dato che in questo modo il campo che la identifica avrà una dimensione costante.

Il tipo di header per la nostra risorsa sarà:

TResHeader = record
DataSize: DWORD; // dimensione dei dati
HeaderSize: DWORD; // dimensione di questo record
  ResType: DWORD; // lo word = $FFFF => ordinal
ResId: DWORD; // lo word = $FFFF => ordinal
DataVersion: DWORD; // *
MemoryFlags: WORD;
LanguageId: WORD; // *
Version: DWORD; // *
Characteristics: DWORD; // *
end;

Nella quale i campi contrassegnati con * non verranno utilizzati.

Ora vediamo la procedura con la quale creiamo il file risorsa:

procedure CreaFileRisorsa(
InputDataFile, OutputResFile: string; // nomi dei file
ResID: Integer // identificativo della risorsa
);
var
FS, RS: TFileStream;
FileHeader, ResHeader: TResHeader;
Padding: array[0..SizeOf(DWORD)-1] of Byte;
begin

{ Creiamo i 2 file }
FS := TFileStream.Create( // In lettura il file dati da inserire
InputDataFile, fmOpenRead);
RS := TFileStream.Create( // In scrittura il nuovo file di risorsa
OutputResFile, fmCreate);

{ Creiamo l' header - tutti zeri tranne che
l'HeaderSize, ResType e ResID }
FillChar(FileHeader, SizeOf(FileHeader), #0);
FileHeader.HeaderSize := SizeOf(FileHeader);
FileHeader.ResId := $0000FFFF;
FileHeader.ResType := $0000FFFF;

{ Creiamo l' header per il file dati RC_DATA
NOTE: per crearne più di uno basta ripetere i seguenti passi
usando però ogni volta un ID di risorsa differente } 
FillChar(ResHeader, SizeOf(ResHeader), #0);
ResHeader.HeaderSize := SizeOf(ResHeader);
// resource id - FFFF indica che non è una stringa
ResHeader.ResId := $0000FFFF or (ResId shl 16);
// resource type - RT_RCDATA (dalla Windows unit)
ResHeader.ResType := $0000FFFF
or (WORD(RT_RCDATA) shl 16);
// dimensione del file dati da inglobare
ResHeader.DataSize := FS.Size;
// impostare i necessari memory flags
ResHeader.MemoryFlags := $0030;

{ Inserire gli headers nel file di risorsa }
RS.WriteBuffer(FileHeader, SizeOf(FileHeader));
RS.WriteBuffer(ResHeader, SizeOf(ResHeader));

{ Copiare il file dati aperto in lettura dentro il file risorsa }
RS.CopyFrom(FS, FS.Size);

{ aggiungere se necessario dei bit alla fine}
if FS.Size mod SizeOf(DWORD) <> 0 then
RS.WriteBuffer(Padding, SizeOf(DWORD) -
FS.Size mod SizeOf(DWORD));

{ chiude i file }
FS.Free;
RS.Free;
end;

Per utilizzarla :

CreaFileRisorsa('test.exe','miarisorsa.res',100);

Il risultato di questo procedimento è un file di risorsa che potremo integrare in una applicazione, e che però per essere estratto dovremo usare una funzione di recupero risorse che usi il numero ResId per identificare la nostra risorsa:

var
  RS: TResourceStream;
begin
  // Crea lo stream relativo alla risorsa
  RS := TResourceStream.CreateFromID(HInstance, 100, RT_RCDATA);
....
....

 

 

Attachments:
Download this file (Inglobare_un_file.zip)Inglobare_un_file.zip[ ]1078 Kb
Download this file (rcdatademo.zip)rcdatademo.zip[ ]3 Kb
Ultimo aggiornamento ( Sabato 19 Giugno 2010 19:57 )