this slowpoke moves

Include Options in Executable

Um Programmoptionen zu sichern, werden meistens INI, DAT oder SAV Dateien verwendet, um Textinhalte oder Fensteroptionen nicht immer wieder neu zu bestätigen. Diese Dateien sind einsichtlich, können verändert oder gelöscht werden. Es lassen sich aber auch Optionen innerhalb der EXE-Dateien sichern, die nicht einsichtlich oder veränderbar sind. 

Dazu wird der Ressourcenbereich der EXE-Datei erweitert und die Daten in die EXE-Datei integriert, und zwar sodass der User nichts davon mitbekommt.

Das folgende Beispiel zeigt, wie sich solche Daten sichern lassen.

Unit ExeEnclosure.pas
UNIT ExeEnclosure;

INTERFACE

uses
  Windows, Controls, SysUtils, Forms, StrUtils, Classes, Dialogs, ShellAPI;
  function  InitializeEnclosure( var DataStream: TMemoryStream ): Boolean;
  function  FinalizeEnclosure  ( var DataStream: TMemoryStream ): Boolean;
  procedure SaveEnclosure      ( var DataStream: TMemoryStream );

IMPLEMENTATION

function OriginalExeName: TFileName;
  var
         S : string;
  begin
  Result := Application.ExeName;
  if LeftStr( ExtractFileName( Application.ExeName ), 6 )<>'CopyOf' then Exit;
  S := ExtractFileName( Application.ExeName );
  Delete( S, 1, 6 );
  Result := ExtractFilePath( Application.ExeName ) + S;
end;

function TempExeName: TFileName;
  begin
  Result := Application.ExeName;
  if LeftStr( ExtractFileName( Application.ExeName ), 6)='CopyOf' then Exit;
  Result :=   ExtractFilePath( Application.ExeName ) + 'CopyOf'
            + ExtractFileName( Application.ExeName );
end;

function EndSignOff: string;
  begin
  Result := 'EnclosureFor' + ExtractFileName( OriginalExeName );
end;

function TryAndDelete( FileName: TFileName ): Boolean;
  var
         i : Integer;
  begin
  Result := false;
  if not FileExists( FileName ) then begin
    Result := true;
    Exit;
  end;
  for i := 1 to 50 do begin
    Sleep( 100 );
    if DeleteFile( FileName ) then begin
      Result := true;
      break;
    end;
  end;
  if not Result then begin
    if MessageDlg(  'The file ' + ExtractFileName( FileName )
                  + ' could not be destroyed.',
                     mtWarning, [mbRetry,mbAbort], 0 ) =  mrRetry
    then TryAndDelete( FileName );
  end;
end;

function InitializeEnclosure( var DataStream: TMemoryStream ): Boolean;
  var
         Sign : string; 
         Pos  : Int64; 
  begin
  Result := false;
  if ( Application.ExeName=TempExeName ) and ( FileExists( OriginalExeName ) )     
    then begin
    TryAndDelete( OriginalExeName );
    DataStream.LoadFromFile( Application.ExeName );
    DataStream.SaveToFile( OriginalExeName );                                      
    ShellExecute( 0, nil, PChar( OriginalExeName ), nil, nil, SW_HIDE );           
    Halt;                                                                          
  end;
  if ( Application.ExeName=OriginalExeName ) and ( FileExists( TempExeName ) )     
    then begin
    TryAndDelete( TempExeName );                                                   
    Halt;                                                                          
  end;
  DataStream.LoadFromFile( Application.ExeName );                                  
  DataStream.Position := DataStream.Size - Length( EndSignOff );                   
  SetLength( Sign, Length( EndSignOff ) );                                         
  DataStream.ReadBuffer( Sign[1], Length( EndSignOff ) );                          
  if Sign = EndSignOff then begin                                                  
    Result := true;
    DataStream.Position := DataStream.Size - Length( EndSignOff ) - SizeOf( Pos ); 
    DataStream.ReadBuffer( Pos, SizeOf( Pos ) );                                   
    DataStream.Position := Pos;                                                    
  end;
end;

function FinalizeEnclosure( var DataStream: TMemoryStream ): Boolean;                     
  var                                                                                     
         TempStream : TMemoryStream; 
         BytesCount : Int64;        
         Sign       : string;      
         Pos        : Int64;      
  begin
  Result := false;
  if ( Application.ExeName=OriginalExeName ) and ( not FileExists( TempExeName ) ) 
    then begin
    DataStream.LoadFromFile( Application.ExeName );                                
    DataStream.Position := DataStream.Size - Length( EndSignOff );                 
    SetLength( Sign, Length( EndSignOff ) );                                       
    DataStream.ReadBuffer( Sign[1], Length( EndSignOff ) );                        
    if Sign = EndSignOff then begin                                                
      DataStream.Position := DataStream.Size - Length( EndSignOff )-SizeOf( Pos ); 
      DataStream.ReadBuffer( Pos, SizeOf( Pos ) );                                 
    end;                                                                           
    TempStream  := TMemoryStream.Create;                                           
    try                                                                            
      BytesCount := DataStream.Position;                                           
      DataStream.Position := 0;                                                    
      TempStream.CopyFrom( DataStream, BytesCount );                               
      DataStream.Clear;                                                            
      TempStream.Position := 0;                                                    
      DataStream.CopyFrom( TempStream, BytesCount );                               
    Finally FreeAndNil( TempStream ); end;                                         
    Result := true;
  end;
end;

procedure SaveEnclosure( var DataStream: TMemoryStream );
  begin
  DataStream.WriteBuffer( EndSignOff[1], Length( EndSignOff ) );
  DataStream.SaveToFile( TempExeName );                                            
  ShellExecute( 0, nil, PChar( TempExeName ), nil, nil, SW_HIDE );                 
end;
END.
Unit1 :
uses ExeEnclosure

//

procedure TForm1.FormCreate( Sender: TObject );
  var
          DataStream : TMemoryStream;
          BytesCount : Integer;
          MemText    : string;
          FormBounds : TRect;
  begin
  DataStream := TMemoryStream.Create;
  try
    if InitializeEnclosure( DataStream ) then begin
      DataStream.ReadBuffer( BytesCount, SizeOf( BytesCount ) );
      SetLength( MemText, BytesCount );
      DataStream.Read( MemText[1], BytesCount );
      DataStream.ReadBuffer( FormBounds, SizeOf( FormBounds ) );
      memTest.Text     := MemText;                               
      Form1.BoundsRect := FormBounds;                            
    end;
  Finally  FreeAndNil( DataStream );   end;
end;

procedure TForm1.FormCloseQuery( Sender: TObject; var CanClose: Boolean );
  var
          DataStream : TMemoryStream; 
          BytesCount : Integer;      
          MemText    : string;      
          Pos        : Int64;      
          FormBounds : TRect;     
  begin
  DataStream := TMemoryStream.Create;
  try
    if FinalizeEnclosure( DataStream ) then begin                 
      Pos        := DataStream.Position;                          
      MemText    := memTest.Text;                                 
      BytesCount := Length( MemText );                            
      FormBounds := Form1.BoundsRect;
      DataStream.WriteBuffer( BytesCount, SizeOf( BytesCount ) );
      DataStream.WriteBuffer( MemText[1], BytesCount );           
      DataStream.WriteBuffer( FormBounds, SizeOf( FormBounds ) ); 
      DataStream.WriteBuffer( Pos, SizeOf( Pos ) );
      SaveEnclosure( DataStream );                                
    end;
  Finally   FreeAndNil( DataStream );   end;
end;

END.

NB :
  Initialization
  Finalization.

Keine Kommentare:

Kommentar veröffentlichen

Beliebte Posts

Translate