IncludeBinary mit allen Dateitypen : CatchFile()

Hier könnt Ihr gute, von Euch geschriebene Codes posten. Sie müssen auf jeden Fall funktionieren und sollten möglichst effizient, elegant und beispielhaft oder einfach nur cool sein.
Benutzeravatar
Olaf
Beiträge: 117
Registriert: 20.04.2006 14:51
Wohnort: 66606 St.Wendel (Niederlinxweiler, Dr.Albert-Schweitzer-Str.9)
Kontaktdaten:

IncludeBinary mit allen Dateitypen : CatchFile()

Beitrag von Olaf »

IncludeBinary unterstützt bei PureBasic mit den "Catch..."-Befehlen bisher nur
das Einfügen von Grafiken und Sounds. Es ist jedoch möglich, alle Dateitypen
in ein Executable einzubinden und später wieder zu "catchen".
Das ist insbesondere dann nützlich, wenn man eine Standalone-Setup.exe für ein Programm
erstellen will, die sich selbst entpackt und alle DLLs, Bitmaps oder sonstige Dateien
aus sich heraus erstellen kann. Da mit Pointern gearbeitet wird und somit in der
CatchFile()-Prozedur keine Codespezifischen Variablen vorkommen, sollte der Code in
allen anderen Codes problemlos einzubinden sein. Zudem kann durch die Arbeit mit Pointern
die Prozedur beliebig oft für verschiedene Dateien verwendet werden.

Code: Alles auswählen

DataSection
  filestart:                                 ;StartLabel (Position)
  IncludeBinary "C:\WINDOWS\explorer.exe"    ;...oder irgendeine andere Datei (hab hier den
                                             ;Explorer gewählt, damit der Code, ohne umgeschrieben
                                             ;werden zu müssen, getestet werden kann)
  fileend:                                   ;EndLabel (Position) wichtig zum berechnen
                                             ;der Datenlänge (siehe unten)
EndDataSection

Procedure CatchFile(FileID,FileName$,Includesection,Length)
  ;FileID :         FileID ist die #FileID, die die Datei später erhalten wird.
  ;FileName :       Es wird die Datei mit dem Namen FileName$ erstellt
  ;IncludeSection : Als IncludeSection muss der Pointer auf das StartLabel
  ;                 des IncludeBinary angegeben werden (hier: ?filestart)
  ;Length :         Length als Datenlänge berechnet sich als Differenz von EndPointer
  ;                 und StartPointer des betroffenen IncludeBinarys.
  ;                 Handelt es sich um mehrere IncludeBinaries, kann als
  ;                 EndPointer auch das StartLabel des nächsten IncludeBinarys
  ;                 angegeben werden:
  ;
  ;                 DataSection
  ;                   file1:
  ;                   IncludeBinary "C:\WINDOWS\notepad.exe"
  ;                   file2:
  ;                   IncludeBinary "C:\WINDOWS\system32\logon.scr"
  ;                   endfiles:
  ;                 EndDataSection
  ;
  ;                 In diesem Fall wäre Length der ersten Datei gleich
  ;                 ?file2-?file1 und als IncludeSection müsste ?file1 angegeben werden.
  ;                 Die letzte Datei in einem solchen DataSection-Block muss natürlich
  ;                 ein eigenes EndLabel erhalten (hier: ?endfiles).
  If CreateFile(FileID,FileName$)
    WriteData(FileID,Includesection,Length)
    CloseFile(FileID)
  EndIf
EndProcedure

;Beispielaufruf:
CatchFile(0,GetHomeDirectory()+"\Desktop\explorer2.exe",?filestart,?fileend-?filestart)
Zuletzt geändert von Olaf am 26.07.2006 19:29, insgesamt 1-mal geändert.
PB 4.xx (Windows & Linux & Mac OS X)
Treffen sich 2 Kurven in der Unendlichkeit. Sagt die eine zur anderen: "Hau ab aus meinem Definitionsbereich oder ich leite dich ab!"
Darauf die andere: "Mach nur! Ich bin die e-Funktion." :lol:
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Code: Alles auswählen

CreateFile(FileID,FileName$)
Die Erstellung der Datei sollte aber überprüft werden, kann sonst böse
Abstürze geben.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Olaf
Beiträge: 117
Registriert: 20.04.2006 14:51
Wohnort: 66606 St.Wendel (Niederlinxweiler, Dr.Albert-Schweitzer-Str.9)
Kontaktdaten:

Beitrag von Olaf »

@ts-soft
Das wollte ich eigentlich dem PB-User überlassen, dafür zu sorgen
(is nicht so, als hätte ich nicht dran gedacht).
Der kann dann ja seine eigenen ProcedureReturns einbauen.
Aber stimmt schon.
PB 4.xx (Windows & Linux & Mac OS X)
Treffen sich 2 Kurven in der Unendlichkeit. Sagt die eine zur anderen: "Hau ab aus meinem Definitionsbereich oder ich leite dich ab!"
Darauf die andere: "Mach nur! Ich bin die e-Funktion." :lol:
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Es geht nicht um ProcedureReturn, es geht darum, wenn das CreateFile
fehlschlägt, ein WriteData den PC zum Absturz bringen könnte.

Also immer so:

Code: Alles auswählen

If CreateFile(FileID,FileName$)
  WriteData(FileID,Includesection,Length)
  CloseFile(FileID)
EndIf 
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Olaf
Beiträge: 117
Registriert: 20.04.2006 14:51
Wohnort: 66606 St.Wendel (Niederlinxweiler, Dr.Albert-Schweitzer-Str.9)
Kontaktdaten:

Beitrag von Olaf »

@ts-soft
Ja, ich weiß, war ehrlich gesagt einfach zu faul, das reinzupacken, wird aber erledigt.
PB 4.xx (Windows & Linux & Mac OS X)
Treffen sich 2 Kurven in der Unendlichkeit. Sagt die eine zur anderen: "Hau ab aus meinem Definitionsbereich oder ich leite dich ab!"
Darauf die andere: "Mach nur! Ich bin die e-Funktion." :lol:
Benutzeravatar
Olaf
Beiträge: 117
Registriert: 20.04.2006 14:51
Wohnort: 66606 St.Wendel (Niederlinxweiler, Dr.Albert-Schweitzer-Str.9)
Kontaktdaten:

Beitrag von Olaf »

@ts-soft
besser so?
PB 4.xx (Windows & Linux & Mac OS X)
Treffen sich 2 Kurven in der Unendlichkeit. Sagt die eine zur anderen: "Hau ab aus meinem Definitionsbereich oder ich leite dich ab!"
Darauf die andere: "Mach nur! Ich bin die e-Funktion." :lol:
Benutzeravatar
ts-soft
Beiträge: 22292
Registriert: 08.09.2004 00:57
Computerausstattung: Mainboard: MSI 970A-G43
CPU: AMD FX-6300 Six-Core Processor
GraKa: GeForce GTX 750 Ti, 2 GB
Memory: 16 GB DDR3-1600 - Dual Channel
Wohnort: Berlin

Beitrag von ts-soft »

Olaf hat geschrieben:@ts-soft
besser so?
Ja :wink:
Wir sind hier schließlich bei Code, Tipps und Tricks. Bei vielen Dingen kann
man diese Überprüfung mal vernachlässigen, aber so Dinge wie
Dateierstellung, Speicherreservierung usw. sollten immer gescheckt werden.
PureBasic 5.73 LTS | SpiderBasic 2.30 | Windows 10 Pro (x64) | Linux Mint 20.1 (x64)
Nutella hat nur sehr wenig Vitamine. Deswegen muss man davon relativ viel essen.
Bild
Benutzeravatar
Leonhard
Beiträge: 602
Registriert: 01.03.2006 21:25

Beitrag von Leonhard »

Ich denke mal, das wenn man schon mit Catch arbeitet man sich den FileName$ ersparen möchte und die Datei auch geöffnet werden sollte.
Daher habe ich folgenen Code geschreieben (bin mir nur nicht einig, ob ich ReadFile(...) oder OpenFile(...) benutzen soll).

Code: Alles auswählen

;// Beschreibung:
;//   Lädt die angegebene Datei 'FileID' von der angegebenen
;//   Speicheradresse. Wenn #PB_Any als '#Image' Parameter
;//   verwendet wird, dann wird die Nummer des neuen Image
;//   als 'Ergebnis' zurückgegeben. Sonst wir der Handle der
;//   FileID zurückgegeben. Auch auslesbar mit FileID(...).
;//   Sie können in der Datei ausschließlich nur
;//   Lese-Operationen ausführen.
;//   
;//   Dieser Befehl ist nützlich in Verbindung mit dem
;//   'IncludeBinary' PureBasic Schlüsselwort. Damit können
;//   Dateien mit in das Executable gepackt werden. Nichts-
;//   destotrotz, benutzen Sie diese Option mit Bedacht,
;//   da hiermit mehr Speicher benötigt wird, als wenn die
;//   Datei in einer externen Datei gespeichert wird (die
;//   Datei befindet sich im Speicher des Executable und
;//   auch geladen im physikalischen Speicher).
;// Parameter:
;//   FileID
;//     Die FileID ist die ID der Datei.
;//     Wenn #PB_Any als 'FileID' Parameter verwendet wird,
;//     dann wird die neue Datei-Nummer als 'Ergebnis'
;//     zurückgegeben.
;//   *Memory
;//     Die Speicheradresse, wo sich die Datei befindet.
;//   Length
;//     Die Länge der Speicheradresse.
;// Rückgabewert:
;//   Der Rückgabewert ist der Handle der FileID (auch
;//   ermittelbar mit FileID(...)) oder wenn in den
;//   'FileID'-Parameter #PB_Any geschrieben wurde die
;//   FileID.
;// Beispiel:
;//   DataSection
;//     file1:
;//     IncludeBinary "C:\WINDOWS\notepad.exe"
;//     file2:
;//     IncludeBinary "C:\WINDOWS\system32\logon.scr"
;//     endfiles:
;//   EndDataSection
;//   
;//   In diesem fall werden die Dateien so eingelanden:
;//   Datei1: CatchFile(XXX, ?file1, ?file2-?file1)
;//   Datei2: CatchFile(XXX, ?file1, ?endfiles-?file1)
Procedure,l CatchFile(FileID, *Memory, Length)
  Protected FileID, ReturnFileID, FileName$
  FileName$=GetEnvironmentVariable("TMP")+"\"+MD5Fingerprint(*Memory, Length)+".tmp")
  ReturnFileID = CreateFile(FileID, FileName$)
  If FileID = #PB_Any
    FileID = ReturnFileID
  EndIf
  If FileID
    WriteData(FileID, *Memory, Length)
    CloseFile(FileID)
  Else
    ProcedureReturn 0
  EndIf
  ReturnFileID = ReadFile(FileID, FileName$)
  ProcedureReturn ReturnFileID
EndProcedure
Zuletzt geändert von Leonhard am 28.07.2006 12:32, insgesamt 1-mal geändert.
myself
Beiträge: 67
Registriert: 18.03.2006 12:48

Beitrag von myself »

Nur liegt der unterschied darin das Catch befehle von PB die datei nicht auf die festplatte schreiben. wenn ich dann den filebuffer von so einer CatchFile geöffneten datei einlest verbraucht das 2x so viel speicher wie die datei groß ist. Ich würde versuchen da mit FreeMemory was zu drehen, aber kA ob das funktioniert.
pankgraf
Beiträge: 29
Registriert: 10.07.2006 21:36
Wohnort: Berlin
Kontaktdaten:

Beitrag von pankgraf »

@myself
Was du schreibst ist richtig.
Olaf hat geschrieben:IncludeBinary unterstützt bei PureBasic mit den "Catch..."-Befehlen bisher nur das Einfügen von Grafiken und Sounds. Es ist jedoch möglich, alle Dateitypen in ein Executable einzubinden und später wieder zu "catchen".
Das ist insbesondere dann nützlich, wenn man eine Standalone-Setup.exe für ein Programm erstellen will, die sich selbst entpackt und alle DLLs, Bitmaps oder sonstige Dateien aus sich heraus erstellen kann. Da mit Pointern gearbeitet wird und somit in der CatchFile()-Prozedur keine Codespezifischen Variablen vorkommen, sollte der Code in allen anderen Codes problemlos einzubinden sein. Zudem kann durch die Arbeit mit Pointern die Prozedur beliebig oft für verschiedene Dateien verwendet werden.
Doch die Vorteile, die sich durchs Olaf's Idee ergeben, sind so groß, daß man unbedingt dieses Projekt weiter verfolgen muß.
Leonhard scheint eine ähnliche Ansicht zu haben, sonst hätte er doch nicht eine verbesserte Prozedur geliefert.

@Leonhard
Es wäre sehr freundlich von dir, wenn du deine Prozedur durch einen Prozedur-Aufruf, wie Olaf es vorgemacht hat, erweiterst.
Hier lesen auch eine große Zahl von Anfängern mit, die nicht unbedingt wissen, woher du *memory und length nimmst. Allen Anderen erleichtert es das schnelle Testen.
Vista, openSuse 11.1, Win2k
Antworten