Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi INI in EXE einbinden (https://www.delphipraxis.net/48039-ini-exe-einbinden.html)

N47R0N 19. Jun 2005 20:10


INI in EXE einbinden
 
Hi @ all

Ich weiß das meine Überschrift nicht gerade gut ist , denn ich meine nicht wie man eine EXE dazu bringt daten aus einer INI zu verwenden sondern :

Ich will wissen ob es möglich ist an eine EXE datei eine INI anhängen kann die beim Ausführen der EXE erst in ein bestimmten Ordner installiert wird .

So soll das ganse funktionieren :

Mein Hauptprogramm heist z.B Start.exe und ist in einem Ordner ( egal welchem ) . Die Start.exe ist darauf angewiesen bestimmte Daten aus einer INI datei zu lesen .

Im Selben Ordner soll sich eine art Editor befinden . Den Öffnet man und kann gans leicht seine Angaben machen die in die INI geschrieben werden . Wenn man nun im Editor auf Fertig stellen drückt soll die INI datei in die Start.exe eingefügt werden .

Wenn die Start.exe nun ausgeführt wird , soll dann wie gesagt die INI in einen bestimten Ordner entpackt werden .


Leider habe ich keinen schimmer von solchen vorgängen und hoffe Unterstützung .

Danke

glkgereon 19. Jun 2005 20:36

Re: INI in EXE einbinden
 
wie Wäre es mit

Delphi-Quellcode:
ST:=TStringList.Create;
ST.Add('[Dings]');
ST.Add('Achso = 1');
ST.Add('[Brummli]');
ST.Add('DingensDa = 2');
ST.Add('UnUeberhauptUndSo = Sodele');
ST.Add('Letztes = Allerletzes');
ST.SaveToFile('Folder/File.ini');
oder nich?

Edit(Vergessen):
Das ganze in Verbindung mit nem TFileStream der die entsprechenden Stellen ersetzt...
dass müsste man halt mit höchstgrenzen für die StringLänge machen, sodass der Rest mit Leerzeichen gefüllt wird, die im Add-Aufruf mit nem Statischen Trim() wieder gekillt werden könnten....

N47R0N 19. Jun 2005 20:41

Re: INI in EXE einbinden
 
Ich weiß wie man eine INI erstellt nur will ich wissen wie man sie an eine EXE Binde und dafür sorgt das wenn die EXE ausgeführt wird dir INI mit ihren gansen inhalt der schon bearbeitet wurde in einen Ordner entpackt und von der EXE benutzt werden kan.

glkgereon 19. Jun 2005 20:45

Re: INI in EXE einbinden
 
ja so:

(im OnCreate oder so aufrufen...)

Delphi-Quellcode:
procedure CreateIni;
var SL: TStringList;
begin
  SL:=TStringList.Create;
  SL.Add(Trunc('[Dings]                  '));
  SL.Add(Trunc('Achso = 1                 '));
  SL.Add(Trunc('[Brummli]                '));
  SL.Add(Trunc('DingensDa = 2             '));
  SL.Add(Trunc('UnUeberhauptUndSo = Sodele'));
  SL.Add(Trunc('Letztes = Allerletzes    '));
  SL.SaveToFile('Folder/File.ini');
  SL.Free;
end;
wobei das was halt innerhalb der Trunc() steht geändert werden müsste

das Ändern:
Hier im Forum suchenTFileStream

malo 19. Jun 2005 20:45

Re: INI in EXE einbinden
 
Zitat:

Zitat von N47R0N
Ich weiß wie man eine INI erstellt nur will ich wissen wie man sie an eine EXE Binde und dafür sorgt das wenn die EXE ausgeführt wird dir INI mit ihren gansen inhalt der schon bearbeitet wurde in einen Ordner entpackt und von der EXE benutzt werden kan.

Ich verstehe dein Problem grad nicht :gruebel:

glkgereon hat doch so einen Weg gezeigt. Das ganze dann ins Oncreate des Forms (bzw. wahlweise auch in die Projektdatei) schreiben und die Exe starten ;)

Hansa 19. Jun 2005 20:46

Re: INI in EXE einbinden
 
Was soll denn das ? Entweder wird was fest eincompiliert in die EXE, oder es kommt sonstwo hin, z.B. INI. Es geht nur darum EBEN NICHTS an der Exe zu ändern !! Genau das willst du aber machen. Wenn jetzt jemand eine Fehlermeldung angibt, dann kannst du es eventuell nicht mal mehr genau lokalisieren, sofern an der EXE rumgefummelt wurde. Also : Wozu soll das gut sein ?

N47R0N 19. Jun 2005 20:58

Re: INI in EXE einbinden
 
damit wollte ich einstellungen an der fertigen exe vornehmen ohne stark in den eigendlichen source ein zu greifen

Hansa 19. Jun 2005 21:04

Re: INI in EXE einbinden
 
So macht man das aber nicht ! Dafür sind doch INIs usw. da. Es ist viel einfacher eine Ini zu verändern, die von einer EXE ausgelesen wird, als die EXE zu verbiegen. 8) Natürlich muß der Source in der Lage sein, die INI richtig zu verarbeiten. Notfalls EXE+INI neu ausliefern. Zumindest nicht ein Programm, das eine vorhandene EXE vergewaltigt.

glkgereon 19. Jun 2005 21:12

Re: INI in EXE einbinden
 
wieso Hansa?

man müsste Halt nur versuchen für den IniTeil den String vorerst eindeutig zu machen...zum finden.

Genau hier sehe auch ich dass Problem:
dass man eben NIE mit 100%iger Sicherheit sagen kann: Dieser String kommt hier, und NUR hier vor in der exe...man kann also nie ganz ausschließen dass man ausversehen ein stückchen "code" verhackstückt.

Ist der String richtig gewählt sollte dieses Problem imho jedoch praktisch ausgeschlossen sein...

malo 19. Jun 2005 21:15

Re: INI in EXE einbinden
 
Zitat:

Zitat von glkgereon
wieso Hansa?

man müsste Halt nur versuchen für den IniTeil den String vorerst eindeutig zu machen...zum finden.

Genau hier sehe auch ich dass Problem:
dass man eben NIE mit 100%iger Sicherheit sagen kann: Dieser String kommt hier, und NUR hier vor in der exe...man kann also nie ganz ausschließen dass man ausversehen ein stückchen "code" verhackstückt.

Ist der String richtig gewählt sollte dieses Problem imho jedoch praktisch ausgeschlossen sein...

Naja, theoretisch könnte man das ganze auch disassemblieren und dann via Assembler die richtige Stelle auslesen und beschreiben. Ob sich der ganze Aufwand jedoch lohnt, ist fraglich ;)

glkgereon 24. Jun 2005 20:40

Re: INI in EXE einbinden
 
nö, so in etwa...(achtung, jetzt so spontan nach 1 Woche PC-Entzug *zitter* *sabber* ;) )
guckt ma drüber ob die ganzen namen so stimmen...aber das grundkonzept sollte gehen.

wie gesagt, es KANN schiefgehen. aber je höher Max ist, desto

Delphi-Quellcode:
const
  Max: Integer = 20; //Länge der Strings

function Fill(Val:String):String;
var i:Integer;
begin
  for i:=1 to Max-Length(Val) do Result:=Result+' ';
  Result:=Val+Result;
end;

procedure ReplaceIniInExe(Rep, RepWith: TStringList);
var FS: TFileStream;
    Buf: String[Max];
begin
  FS:=TFileStream.Create('Bla.Exe',fmShareExclusive or fmReadWrite);
  while FS.Position<FS.Size do
    begin
    FS.Read(Buf,Max);
    if Rep.IndexOf(Trim(Buf))>-1 then
      begin
      FS.Position:=FS.Position-Max;
      FS.Write(Fill(RepWith.Strings[Rep.IndexOf(Trim(Bux))]));
      end;
    end;
  FS.Free;
end;

NicoDE 24. Jun 2005 20:47

Re: INI in EXE einbinden
 
Du kannst die Daten an die Exe anhängen (zum Beispiel mit einem TMemoryStream).
Den Start der anghängten Daten kann man zur Laufzeit anhand des PE/COFF-Headers aus dem Image auslesen.
(so funktioniert das auch bei etlichen selbsextrahierenden Programmen)

Einfacher Weg die Ini an die Exe anzuhängen:
Code:
copy /B Project1.exe + /B Foo.ini Project1Foo.exe
Und zur Laufzeit an die Daten kommen:
Delphi-Quellcode:
unit PE32Stub {platform};

interface

function GetOverlay(var Buffer: Pointer): Cardinal;
procedure FreeOverlay(var Buffer: Pointer);

implementation

uses
  Windows;

// types/defs (mostly Delphi 2/3 stuff)

type
  LONG = Longint;

const
  IMAGE_DOS_SIGNATURE = $5A4D;
type
  TImageDosHeader = packed record
      e_magic  : WORD;
      e_cblp   : WORD;
      e_cp     : WORD;
      e_crlc   : WORD;
      e_cparhdr : WORD;
      e_minalloc: WORD;
      e_maxalloc: WORD;
      e_ss     : WORD;
      e_sp     : WORD;
      e_csum   : WORD;
      e_ip     : WORD;
      e_cs     : WORD;
      e_lfarlc : WORD;
      e_ovno   : WORD;
      e_res    : array [0..3] of WORD;
      e_oemid  : WORD;
      e_oeminfo : WORD;
      e_res2    : array [0..9] of WORD;
      e_lfanew : LONG;
  end;
  TImageFileHeader = packed record
    Machine            : WORD;
    NumberOfSections   : WORD;
    TimeDateStamp      : DWORD;
    PointerToSymbolTable: DWORD;
    NumberOfSymbols    : DWORD;
    SizeOfOptionalHeader: WORD;
    Characteristics    : WORD;
  end;
const
  IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16;
  IMAGE_NT_OPTIONAL_HDR_MAGIC = WORD($010B);
type
  TImageDataDirectory = record
    VirtualAddress: DWORD;
    Size         : DWORD;
  end;
  TImageOptionalHeader = packed record
    Magic                     : WORD;
    MajorLinkerVersion        : BYTE;
    MinorLinkerVersion        : BYTE;
    SizeOfCode                : DWORD;
    SizeOfInitializedData     : DWORD;
    SizeOfUninitializedData   : DWORD;
    AddressOfEntryPoint       : DWORD;
    BaseOfCode                : DWORD;
    BaseOfData                : DWORD;
    ImageBase                 : DWORD;
    SectionAlignment          : DWORD;
    FileAlignment             : DWORD;
    MajorOperatingSystemVersion: WORD;
    MinorOperatingSystemVersion: WORD;
    MajorImageVersion         : WORD;
    MinorImageVersion         : WORD;
    MajorSubsystemVersion     : WORD;
    MinorSubsystemVersion     : WORD;
    Win32VersionValue         : DWORD;
    SizeOfImage               : DWORD;
    SizeOfHeaders             : DWORD;
    CheckSum                  : DWORD;
    Subsystem                 : WORD;
    DllCharacteristics        : WORD;
    SizeOfStackReserve        : DWORD;
    SizeOfStackCommit         : DWORD;
    SizeOfHeapReserve         : DWORD;
    SizeOfHeapCommit          : DWORD;
    LoaderFlags               : DWORD;
    NumberOfRvaAndSizes       : DWORD;
    DataDirectory             :
      array [0..IMAGE_NUMBEROF_DIRECTORY_ENTRIES - 1] of TImageDataDirectory;
  end;
const
  IMAGE_NT_SIGNATURE = DWORD($00004550);
type
  TImageNtHeaders = packed record
    Signature    : DWORD;
    FileHeader   : TImageFileHeader;
    OptionalHeader: TImageOptionalHeader;
  end;
const
  IMAGE_SIZEOF_SHORT_NAME = 8;
type
  TImageSectionHeader = packed record
    Name                  : array [0..IMAGE_SIZEOF_SHORT_NAME - 1] of AnsiChar;
    Misc                  : record
      case Integer of
        0: (PhysicalAddress: DWORD);
        1: (VirtualSize   : DWORD);
    end;
    VirtualAddress        : DWORD;
    SizeOfRawData         : DWORD;
    PointerToRawData      : DWORD;
    PointerToRelocations  : DWORD;
    PointerToLinenumbers  : DWORD;
    NumberOfRelocations   : WORD;
    NumberOfLinenumbers   : WORD;
    Characteristics       : DWORD;
  end;

// GetOverlay

function GetOverlay(var Buffer: Pointer): Cardinal;
const
  INVALID_FILE_SIZE = DWORD(-1);
  INVALID_SET_FILE_POINTER = DWORD(-1);
var
  FileName: array [0..MAX_PATH] of Char;
  FileHandle: THandle;
  FileSizeLo: DWORD;
  DosHeader: TImageDosHeader;
  BytesRead: DWORD;
  NtHeaders: TImageNtHeaders;
  Offset: DWORD;
  Section: WORD;
  SecHeader: TImageSectionHeader;
begin
  Result := 0;
  Buffer := nil;
  if GetModuleFileName(HMODULE(nil), FileName, MAX_PATH) <= 0 then
    Exit;
  FileHandle := CreateFile(FileName, GENERIC_READ, FILE_SHARE_READ, nil,
    OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, THandle(nil));
  if INVALID_HANDLE_VALUE = FileHandle then
    Exit;
  try
    // Get FileSize
    FileSizeLo := GetFileSize(FileHandle, nil);
    if INVALID_FILE_SIZE = FileSizeLo then
      Exit;
    // Read Headers
    with DosHeader, NtHeaders, NtHeaders.FileHeader, NtHeaders.OptionalHeader do
      if not ReadFile(FileHandle, DosHeader, SizeOf(TImageDosHeader), BytesRead,
          nil) or (BytesRead <> SizeOf(TImageDosHeader)) or
        (e_magic <> IMAGE_DOS_SIGNATURE) or
        (e_lfanew < SizeOf(TImageDosHeader)) or
        (INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle,
          e_lfanew - SizeOf(TImageDosHeader), nil, FILE_CURRENT)) or
        not ReadFile(FileHandle, NtHeaders, SizeOf(TImageNtHeaders), BytesRead,
          nil) or (BytesRead <> SizeOf(TImageNtHeaders)) or
        (Signature <> IMAGE_NT_SIGNATURE) or (NumberOfSections <= 0) or
        (SizeOfOptionalHeader < SizeOf(TImageOptionalHeader)) or
        (INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle,
          SizeOfOptionalHeader - SizeOf(TImageOptionalHeader), nil,
          FILE_CURRENT)) then
        Exit;
    // Read Sections
    Offset := 0;
    for Section := 1 to NtHeaders.FileHeader.NumberOfSections do
    begin
      if not ReadFile(FileHandle, SecHeader, SizeOf(TImageSectionHeader),
        BytesRead, nil) or (BytesRead <> SizeOf(TImageSectionHeader)) then
        Exit;
      if Offset < SecHeader.PointerToRawData + SecHeader.SizeOfRawData then
        Offset := SecHeader.PointerToRawData + SecHeader.SizeOfRawData;
    end;
    if Offset <= 0 then
      Exit;
    Result := FileSizeLo - Offset;
    if Result <= 0 then
      Exit;
    // Get Overlay
    Buffer := VirtualAlloc(nil, Result + 1, MEM_COMMIT, PAGE_READWRITE);
    if not Assigned(Buffer) then
    begin
      Result := 0;
      Exit;
    end;
    try
      if (INVALID_SET_FILE_POINTER = SetFilePointer(FileHandle, Offset, nil,
        FILE_BEGIN)) or
        not ReadFile(FileHandle, Buffer^, Result, BytesRead, nil) or
        (BytesRead <> Result) then
      begin
        VirtualFree(Buffer, 0, MEM_RELEASE);
        Buffer := nil;
        Result := 0;
      end
      else
        PAnsiChar(Buffer)[Result] := #0; // termiating null for strings
    except
      VirtualFree(Buffer, 0, MEM_RELEASE);
      Buffer := nil;
      Result := 0;
    end;
  finally
    CloseHandle(FileHandle);
  end;
end;

procedure FreeOverlay(var Buffer: Pointer);
begin
  if Assigned(Buffer) then
  begin
    VirtualFree(Buffer, 0, MEM_RELEASE);
    Buffer := nil;
  end;
end;

end.
Delphi-Quellcode:
procedure TForm1.FormCreate(Sender: TObject);
var
  Size: Cardinal;
  Buff: Pointer;
  StrLst: TStringList;
  Stream: TMemoryStream;
begin
  Size := GetOverlay(Buff);
  if Assigned(Buff) then
    try
      StrLst := TStringList.Create;
      Stream := TMemoryStream.Create;
      try
        Stream.WriteBuffer(Buff^, Size);
        Stream.Position := 0;
        StrLst.LoadFromStream(Stream);
        // TMemIniFile.SetStrings(StrLst);
        Memo1.Lines.Text := StrLst.Text;
      finally
        StrLst.Free;
        Stream.Free;
      end;
    finally
      FreeOverlay(Buff);
    end;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 03:45 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz