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;
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