[PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Anfängerfragen zum Programmieren mit PureBasic.
Benutzeravatar
H.Brill
Beiträge: 496
Registriert: 15.10.2004 17:42
Wohnort: 66557 Neunkirchen

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von H.Brill »

Axolotl hat geschrieben: 09.09.2024 16:36 NextPackEntry() gibt keinen Zeiger zurück.
Diese Next.... Sachen, die PB oft verwendet sind eigentlich genial. Die geben eigentlich nur 1 oder 0
zurück, also #True oder 'False und sind für Schleifen als Abfrage (meist kopfgesteuert) gedacht, wenn mehrere
Inhalte (z.B. Einträge in der Preferencedatei, dateien einer .zip usw. ) vorhanden sind. Ist dir vorher schon bei
While NextPreferenceKey() begegnet. Und das Next... wird dir noch sehr oft hilfreich sein.

Vielleicht ist dir als BASICler auch EOF(datei) bekannt. Das ist sowas ähnliches, da es auch nur wahr oder falsch zurück gibt
und man es in einer kopfgesteuerten Schleife verwendet : While Eof(datei) <> True oder While Eof(datei) = false

Das sollte für dich zum besseren Verständnis sein.
PB 6.10
Benutzeravatar
HeX0R
Beiträge: 3040
Registriert: 10.09.2004 09:59
Computerausstattung: AMD Ryzen 7 5800X
96Gig Ram
NVIDIA GEFORCE RTX 3060TI/8Gig
Win11 64Bit
G19 Tastatur
2x 24" + 1x27" Monitore
Glorious O Wireless Maus
PB 3.x-PB 6.x
Oculus Quest 2 + 3
Kontaktdaten:

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von HeX0R »

Ich wäre vorsichtig mit sowas (While Eof(datei) <> #True), man sollte sich schon an das halten, was die Hilfe sagt:
Returns nonzero if the read-pointer is at the end of the file or zero if not.
Also richtig ist in der Tat nur

Code: Alles auswählen

While Eof(datei) = 0
(klar oder #False anstatt 0, aber auch hier wäre ich vorsichtig, vielleicht bekommen wir ja mal "echte" boolsche True und False)
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von ChrigiGee »

Hoi Axolotl,

OK, dort liegt er begraben, mir ist der #PB_String_NoZero über den Weg gelaufen und dachte, dass dieser evtl.
die Lösung wäre, aber das mit AllocMemory() hab ich auch gelesen, war mir nie sicher, ob das evtl. der Punkt gewesen wäre,
und wieder verworfen.

Beim Durchlesen der Hilfe und der Fehlermeldung,
read a null termiinated string at the memory adress
vermutete ich, dass irgendetwas mit dem MD5 String nicht ganz OK sein könnte, resp. dass dieser nicht berechnet wird
anhand compressend oder uncompressed PackedSize oder falsch berechnet.

Auch das mit den 32 Zeichen mutmasste ich, dass es mir mit dem MD5 String zu tun haben könnte und genau dort stoppte,
war für mich auch die Vermutung naheliegend, es handle sich um den.

Habe mich also diesem extrem stark gewidmet in den letzten Stunden.

Bevor ich Deinen Source verwende, versuche ich es mit dem AllocMemory() und lese mich dort noch etwas vertiefter rein.
So kann ich mir auch wieder wissen an eigenen.

Herzlichen Dank für Deine Unterstützung und freut einem doch, wenn man einen uralt Source wieder verwenden kann.

Schönen Abend
Christian
Axolotl hat geschrieben: 09.09.2024 16:36 Hi,

ach ich dachte das wir das thema schon abgearbeitet hatten.....
Also: Was passiert hier eigentlich?
NextPackEntry() gibt keinen Zeiger zurück.
Bevor Du Speicher mit Peek oder Poke verwenden kannst muss er vorhanden sein, z.B.; AllocMemory() oder als @NotEmptyString$
Welchen der unterstützten Packer PlugIns Du verwendest ist egal.

BTW: Ich habe die beiden Proceduren mal (in meinem Stil) erstellt, weil ich überlegt hatte die Grundidee für ein Progrämmchen zu verwenden.....
Wenn Du es probierst, muss Du den Bereich am Ende (siehe hier) an deine Verzeichnisse anpassen und den jeweiligen Procedure Aufruf entkommentieren.
Also 1. CreatePackage() entkommentieren und laufen lassen.
Dann 2. PatchWithPackage() entkommentieren und CreatePackage() wieder kommentieren.

Code: Alles auswählen

CompilerIf #PB_Compiler_IsMainFile ; 
  Global Updater$ = "C:\Temp\Test_update.zip"   ; <- is created 
  Global OldFile$ = "C:\Temp\Test1.txt"         ; <- must exist 
  Global NewFile$ = "C:\Temp\Test2.txt"         ; <- must exist 

; ; this creates a Package (ZIP File) with NewFile$ and MD5 Checksum .... 
; Debug CreatePackage(Updater$, OldFile$, NewFile$) 

; ; this updates OldFile$ with NewFile$ from Package .... 
; Debug PatchWithPackage(Updater$, OldFile$) 
  
CompilerEndIf 
Tipp: Einfach mal die Packet-Datei mit einem Archiver Program (z.B.: 7-zip) anschauen.....

Und hier der Code der beiden Proceduren....

Code: Alles auswählen

UseZipPacker()        ; <-- plugin for Packer 
;                     ;     You need one of these: UseZipPacker(), UseLzmaPacker(), UseTarPacker(), UseBriefLZPacker(). 
UseMD5Fingerprint()   ; <-- plugin for Checksum 


#PACKAGE      = 1   
#FILE_Patch   = 1 

#MD5_SIZE = 32  ; size of MD5 is always 32 chars 

; --- Helper: Ask User for Confirmation ---
; 
Procedure Confirm(Message$)
  If MessageRequester("", Message$, #PB_MessageRequester_Info|#PB_MessageRequester_YesNo) = #PB_MessageRequester_Yes 
    ProcedureReturn #True 
  EndIf 
  ProcedureReturn #False 
EndProcedure


; create the file with the new Patch file 
; 
Procedure CreatePackage(Package$, OldFile$, NewFile$)  ; --- 
  Protected checksumOldFile$, checksumNewFile$, packedFile$ 
  Protected result, *fmem, fsize, bytes 

  If FileSize(Package$) > -1  ; existing file 
    If Confirm("Packet-Datei existiert bereits. " + #LF$ + "Überschreiben?") = #False  
      ProcedureReturn #False  ; don't overwrite the existing file 
    EndIf 
  EndIf 

  checksumOldFile$ = FileFingerprint(OldFile$, #PB_Cipher_MD5)  
  checksumNewFile$ = FileFingerprint(NewFile$, #PB_Cipher_MD5) 
  If checksumOldFile$ = checksumNewFile$ 
    ProcedureReturn #False 
  EndIf 
  
  If CreatePack(#PACKAGE, Package$) 
    ; read file to buffer 
    If ReadFile(#FILE_Patch, NewFile$) 
      fsize = Lof(#FILE_Patch) + #MD5_SIZE 
      *fmem = AllocateMemory(fsize) 
      If *fmem 
        bytes = ReadData(#FILE_Patch, *fmem + #MD5_SIZE, fsize - #MD5_SIZE)  ; keep the 32 byte for md5 
        If bytes 
          Debug "Number of bytes read: " + Str(bytes) + "  " + Str(fsize - #MD5_SIZE) 
          PokeS(*fmem, checksumOldFile$, #MD5_SIZE, #PB_String_NoZero|#PB_Ascii)  ; Writes the strings in ascii

          packedFile$ = ReplaceString(NewFile$, #PS$, "?") ; change PathSeparator with some char not allowed in filenames 
          AddPackMemory(#PACKAGE, *fmem, fsize, packedFile$) 
          result = #True 
        EndIf 
        FreeMemory(*fmem) 
      EndIf 
      CloseFile(#FILE_Patch)
    EndIf 
    ClosePack(#PACKAGE) 
  EndIf 
  ProcedureReturn result ; default is #False 
EndProcedure 


; patch the old file with the new file from Package 
; 
Procedure PatchWithPackage(Package$, OldFile$)  ; --- 
  Protected checksumOldFile$, packed$ 
  Protected result, *fmem, fsize 

  If FileSize(OldFile$) = -1  ; not existing old file 
    ; ERROR 
    ProcedureReturn #False 
  EndIf 

  checksumOldFile$ = FileFingerprint(OldFile$, #PB_Cipher_MD5)  

  If OpenPack(#PACKAGE, Package$) 
    If ExaminePack(#PACKAGE) 
      While NextPackEntry(#PACKAGE)  
        fsize = PackEntrySize(#PACKAGE) 
;Debug "Name: " + PackEntryName(#PACKAGE) + ", Size: " + fsize 

        *fmem = AllocateMemory(fsize) ;, #PB_Memory_NoClear)  
        If *fmem 
          If UncompressPackMemory(#PACKAGE, *fmem, fsize) <> -1 
            packed$ = PeekS(*fmem, #MD5_SIZE, #PB_Ascii)            
            If checksumOldFile$ = packed$  ; 
              If CopyFile(OldFile$, OldFile$ + ".bak") 
                If CreateFile(#FILE_Patch, OldFile$) 
                  WriteData(#FILE_Patch, *fmem + #MD5_SIZE, fsize - #MD5_SIZE) 
                  CloseFile(#FILE_Patch)  
                  result = #True  ; 
                EndIf 
              EndIf 
            EndIf 
          EndIf         
          FreeMemory(*fmem) 
        EndIf 
      Wend
    EndIf 
    ClosePack(#PACKAGE) 
  EndIf 
  ProcedureReturn result ; default #False 
EndProcedure 


CompilerIf #PB_Compiler_IsMainFile ; create a file .... 

  Global Updater$ = "C:\Temp\Test_update.zip"   ; <- is created 
  Global OldFile$ = "C:\Temp\Test1.txt"         ; <- must exist 
  Global NewFile$ = "C:\Temp\Test2.txt"         ; <- must exist 

; ; this creates a Package (ZIP File) with NewFile$ and MD5 Checksum .... 
; Debug CreatePackage(Updater$, OldFile$, NewFile$) 

; ; this updates OldFile$ with NewFile$ from Package .... 
; Debug PatchWithPackage(Updater$, OldFile$) 
  
CompilerEndIf 
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Benutzeravatar
H.Brill
Beiträge: 496
Registriert: 15.10.2004 17:42
Wohnort: 66557 Neunkirchen

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von H.Brill »

Um es mal klar zu stellen :
Mit dem EOF() hatte ich eher an die GW/Quickbasic Variante gedacht, da er ja aus dieser Ecke herkommt.
Er soll es ja auch den Sinn begreifen und da sind altgewohnte Sachen zur Erläuterung besser. Bei den Next...
Sachen geht es ja auch darum, daß man selber keine Schleifen-Abbruch-Bedingung erschaffen muß, sondern die
Next... Variante von PB nimmt.

Die PureBasic - List wäre da eine gute Übung, da leicht zu verstehen.
PB 6.10
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von ChrigiGee »

Hallo @all und einen guten Abend,

Ja, an die kann ich mich noch dunkel erinnern. (EOF() ).
Jetzt werden Sachen auch wieder klarer, hat sich halt auch viel geändert dazwischen.
Wenn man sich erinnern mag so die letzten QBasic oder die letzte Pascal für DOS wo man auch "endlich" mal eine GUI
erschaffen konnte und schwubbs war Windows da.

Was mir aufgefallen ist, bei der erstellten Patch Datei, wird mir leider der komplette Pfad mitgespeichert.
Und zwar von meinem Rechner, was ja nicht unbedingt das wäre, was man gebrauchen kann auf der anderen Seite.

Wer hat schon Verzeichnis
H:\Mein-PB-Test-App\Meine-Patch-Test\meine-neue.exe
Und für die neue Datei Seite bei einem Kunden:
Z:\Meine-Anwendung\Patch-Test\meine-altedatei.exe
Und der Patch liegt dann zum Beispiel:
R:\meine-Patches\Meine-PB-Versuche\Patch\patchipatch.ptc
In der patchipatch.ptc ist die Datei jedoch so abgelegt:
H:\Mein-PB-Test-App\Meine-Patch-Test\meine-neue.exe
Wenn die Patch Datei entpackt würde, würde er es somit auf die Verzeichnisstruktur versuchen.
Ich habe versucht herauszufinden, wo das angegeben wird, bis jetzt habe ich in diese Richtung noch nichts Näheres gefunden.
Ich war der Annahme, es würde nur den Dateinamen übernehmen.

Aber es macht mir sehr viel Spass Eure Informationen versuchen, mit der Struktur, die bei mir besteht abzugleichen.
Braucht manchmal etwas länger, aber ich komme auch noch zu Ziel.

So, ich versuche mich noch etwas den Hilfe-Dateien zu widmen und einen Lösungsansatz zu finden.
Dazwischen teste ich das andere Beispiel mal aus. Vielleicht findet sich auch gleich dort noch einen Lösungshinweis, den ich übersehen hätte.

Einen schönen Abend
Christian
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von ChrigiGee »

Hallo und einen wunderschönen Morgen,
Möge der Tag bei Euch allen so verlaufen wie man IHN sich vorstellt.

Hier habe ich mal, meinen ersten Teil der Arbeit für das Forum wieder zuammengetragen.
Alles ist noch nicht Perfekt, aber so dass man vielleicht den Fortschritt sieht.

Wie gesagt der Source ist noch nicht eliminiert von altem unbenutzem.
Ich hoffe ich kann Heute etwas besser am Ball bleiben.

Herzliche Grüsse aus Bern
Christian


Main Programm GUI:

Code: Alles auswählen

;= GUI Test for the procedure createpatch.pbi and patchit.pbi
;- Top
; -----------------------------------------------------------------------------
;           Name: myPatch app
;    Description: GUI & patch maker + patcher
;         Author: Christian & all of the PureBasic Forum
;           Date: 2024-09-09
;        Version: Beta 1a
;     PB-Version: 6.11
;             OS: WIN 11
;         Credit:
;          Forum:
;     Created by: IceDesign
; -----------------------------------------------------------------------------
; EnableExplicit 

fileEnconding = #PB_UTF8


;}>SecOneA(1)
;| == 1. Aufzählungen (Enummeration) von Controlls
;|   
;| § 1.1 -- Aufliestung der benötigten Elemente der Buttons sowie vorhandener
;| Strings für die weiterführende GUI.
;{<

;}>SecOneB(2)
;|
;|§ 1.2 --  Die Dokumentantion Elemente in dieser Source werden zugleich für die
;|          externe Dokumentantions Generierung mit doxler verwendet und als ASCIIdoc
;|          resp. HTML Datei generiert.
;|          So dass ich über die HTML oder SCIIdoc File gerade eine passende Dokumentation
;|          generier kann ohne weitere bemühungen
;|
;|          REFERENZEN: (Stand 09.09.2024)
;|
;|          https://www.purebasic.fr/german/viewtopic.php?p=353121&hilit=AsciiDoc#p353121
;|          https://tajmone.github.io/doxter/
;|          https://github.com/tajmone/doxter
;|
;|
;|
;| - Enumeration Gadget
Enumeration Gadgets
  #Str_Source_DIR
  #Str_Target_DIR
  #Str_Patch_DIR
EndEnumeration
;{<

;}>SecTwoA(3)
;| == 2.  Global Variablen 
;|
;| § 2.1 --  Variablen welche Global zugewiesen werden und entsprechend auch
;|           über eine Prozedure hinweg beansprucht werden.
;|
;| § 2.2 --  Zuweisen von Dateinamen und Verzeichnisnamen in der Variable
;|
;| - Global
Global Pattern$        ;- Auswahl welcher Dateien verwendet werden

Global File1$          ;- Source Datei für den Patch
Global File2$          ;- Target Datei für den Patch
Global File3$          ;- Patch Datei himself
Global InitialPath1$   ;- Welches  verzeichnis für Source und Target
Global InitialPath2$   ;- Welches  verzeichnis für Source und Target
Global InitialPath3$   ;- Welches Verzeichnis für den Patch himself
                       ;{<

;}>SecThreeA(6) 
;| == 3. Define -  
;|   
;| § 3.1 --  Variablen welche den gleichen "Wert" zugewiesen wird.
;|
;| - Define
Define Pattern
;{<

;}>SecTfourA(7)
;| == 4.    Include der verschiedener Prozeduren
;|  § 4.1   resp. include Elemente vergleichbar PlugIn
;|
;| § 4.2 --  Die erste Include Datei ist die Create Patch Prozedure.
;|           wobei zwei zusätzlich Elemente als wichtig wären wie später gesehen
;|
;| - Include patchmaker Prozedur
XIncludeFile "createpatch.pbi"
;{<

;}>SecTfourB(9)   
;| § 4.1 --  Die nächste Include Datei ist die Prozedure zum erstellen der preferences Datei.
;|           wobei diese "nur" erstellt wird als einmal Datei zur sicherheit.
;|
;| - Include Create first Prefereces File
XIncludeFile "Open_Create_Preferences.pbi"
;{<

;}>SecTfourE(11) 
;| § 4.2 --  Die nächste Include Datei ist die die normale öfnne Preference
;|           Sie wird zum auslesen der gespeicherten Werte der Preferences Datei benötigt
;|           Sie diient zugleich dazu dass garantiert ist, Werte zu haben für die GUI und auch
;|           Patcher Prozeduren
;|
;| - Open Preferences first
IncludeFile "OpenPreferences.pbi"
;{<

;}>SecTfourF(12) 
;| § 4.2 --  Die nächste Datei ist dazu da, eine Datei zu erstellen welche wiederum
;|           nur für den ersten Anwendungsfall besteht, keine Realen Daten vorhanden für die
;|           Pref, sprich Source und Target Datei wurden noch nie angewendet so benötige ich
;|           eine pseudo File.
;|
;| - Create Dir for Preferences & non.del File
CreateDirectory("Prefs")
;|
;|- Create non.del File
OpenFile(0,GetCurrentDirectory()+"\Prefs\not.del")
CloseFile(0)
;{<

;}>SecTfiveA(13) 
;| == 5.    ButtonHandler Prozedure
;|
;| § 5.1 --  Diese Prozedure überprüft welcher Button betätigt wurde und welches Verzeichnis
;|           daraus resultieren als Wert gesetzt werden muss.
;|           Es ist die eihgentlich Abfrage Routine für die Verzeichnisse sowie Dateien.
;{<

;}>SecTsixA(14) 
;|
;| == 6.    Referenzen Include Dateien:
;|
;| § 6.1    Die verschiedenen Include Dateien "PatchMaker" sowie "Preferences"
;|          stammen alle aus dem PureBasic Forum (Deutscsh)
;|          exakte Links zu den entsprechenden Beiträgen werden auch hier zusammen gettragen.
;|
;| § 6.2    Include Datei zum Thema "Preferences"
;|          entsprechend die bestehende Source Beispiele angepasst für die eigene Anwendung.
;|
;|          https://www.purebasic.fr/german/viewtopic.php?t=33055&hilit=preferences
;|
;| § 6.3    Die Include Dateien "PatchMaker" wurden aus folgendem Post Beitrag übernommen:
;|          Die eigentlichen beiden Prozeduren wurden von cyan geschrieben, anhand zweier
;|          Ideen Vorcshläge von Real und ??? umgesetzt.
;|
;|          https://www.purebasic.fr/german/viewtopic.php?t=9908&start=10
;|
;{<

;}>SecTsevenA(15) 
;|
;| == 7.    ButtonHandler Prozedure
;|
;| § 7.1 -- Diese Prozedure überprüft welcher Button betätigt wurde und welches Verzeichnis
;|          daraus resultieren als Wert gesetzt werden muss.
;|          Es ist die eihgentlich Abfrage Routine für die Verzeichnisse sowie Dateien.
;|
;| - Procedure Button-Handler
Procedure ButtonHandler()
  ;| Debug "Button click event on gadget #" + EventGadget()
  ;| wenn man hier den EventGadget mit EventGadget() ermittelt und mit If... abfragt,
  ;| hat man eine Universal-Procedure für alle anfallenden Button-Gadgets
  If EventGadget() = 3 
    ;{<
    
    ;}>SecTeightA(16) 
    ;|
    ;| == 8.    Shared Files
    ;|  § 8.1   Da die Dateien aus den Variablen Files nicht nur in der Hauptanwedung vorkommen und
    ;|          bestehen müssen, werden diese in den jeweiligen Sektionen erneut deklariert als Shared
    ;|          Damit diese an die Prozedur Preferences weiter gegeben werden können.
    ;|          Die Werte Files gehen nach der Sektion EventGadget 1 bis 4 jeweils verlohren
    
    Shared File1$
    Shared File2$
    Shared File3$
    ;{<
    
    ;}>SecTeightB(17) 
    ;| 
    ;| == 8.    Shared Files & Preferences
    ;|
    ;| § 8.2    Die Variablen File werden dank deklaration Shared gespeichert und weiter in Hauptanwedung vorkommen
    ;|          Ebenfals werden Sie umgehend in der Preferences Datei gespeichert über die Procedure CreatePreferences
    ;|          Resp. OpenPreferences.
    
    ;| - Auswahl alte "zu patchende" Datei  
    InitialPath1$ = "C:\Users\cschaer\Documents\my Basic\PureBasic\source.txt"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
    Pattern$ = "executable (*.exe;*.dll)|*.exe;*.dll|Alle Dateien (*.*)|*.*"
    Pattern = 0    ; wir verwenden den ersten von zwei möglichen Pattern als Standard
    File1$ = OpenFileRequester("Bitte Datei zum Laden auswählen", InitialPath1$, Pattern$, Pattern)
    SetGadgetText(#Str_Source_DIR, File1$)
    
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
    ;{<
    
    ;}>SecTeightC(18) 
    ;|
    ;| == 8.    Shared Files & Preferences
    ;|
    ;|  § 8.3   Repetition der Shared Variable File sowie deren weiter reichung  an das Haput Programm und die Speicherung
    ;|          in der Preferences Datei mit den neuen Werten aus der zweiten Sektion "Button Handler"
    ;|          NEU sind die Werte File1$ und File2$ ebenfals in der Preferences vorhanden und werden nach dem Speichern wieder
    ;|          geöffnet zur kontrolle.
    ;|
    ;| - Auswahl Neue "gepatchte" Datei    
  ElseIf EventGadget() = 4
    
    Shared File1$
    Shared File2$
    Shared File3$
    
    InitialPath2$ = "C:\Users\cschaer\Documents\my Basic\PureBasic\target.txt"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
    Pattern$ = "executable (*.exe;*.dll)|*.exe;*.dll|Alle Dateien (*.*)|*.*"
    Pattern = 0    ; wir verwenden den ersten von zwei möglichen Pattern als Standard
    File2$ = OpenFileRequester("Bitte Datei zum Laden auswählen", InitialPath2$, Pattern$, Pattern)
    SetGadgetText(#Str_Target_DIR, File2$)
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
    ;|    
    ;{<
    
    ;}>SecTeightD(19) 
    ;|
    ;| == 8.    Shared Files & Preferences
    ;|
    ;|  § 8.4   Repetition der Shared Variable File sowie deren weiter reichung  an das Haput Programm und die Speicherung
    ;|          in der Preferences Datei mit den neuen Werten aus der ersten und zweiten Sektion "Button Handler"
    ;|          NEU sind die Werte File1$ und File2$ und File3$ ebenfals in der Preferences vorhanden und werden nach dem Speichern wieder
    ;|          geöffnet zur kontrolle.
    ;|
    ;|          Anschliessend wird die Procedure createpatch angesprochen / ausgeführt welche den eigentlichen Patch erstelt
    ;|          Nach dem erstellen des Patch ist die Anwendung verfügbar für das erstellen eines NEUEN Patch nach den gleichen vorgaben.
    ;|
    ;| - Auswahl Patch File (erstellter Patch)
  ElseIf EventGadget() = 5          
    Shared File1$
    Shared File2$    
    Shared File3$
    
    InitialPath3$ = "C:\Users\cschaer\Documents\my Basic\PureBasic\my Patch\new\patch.csp"   ; anfänglichen Pfad für die Anzeige festlegen (kann auch leer sein)
    Pattern$ = "executable (*.exe;*.dll)|*.exe;*.dll|Alle Dateien (*.*)|*.*"
    Pattern = 1    ; wir verwenden den zweiten der möglichen Pattern als Standard
    File3$ = OpenFileRequester("Bitte Datei zum Laden auswählen", InitialPath3$, Pattern$, Pattern)
    SetGadgetText(#Str_Patch_DIR, File3$)
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
    
    createpatch(File1$,File2$,File3$)
    ;|
    ;{<
    
    ;}>SecTeightE(20) 
    ;|
    ;| == 8.     Shared Files & Preferences
    ;|
    ;|  § 8.5    Repetition der Shared Variable File sowie deren weiter reichung  an das Haput Programm
    ;|
    ;|           Die Variablen Shared File1$ bis File3$ werden in diesem Teil zur Sicherheit wiederholt
    ;|           und durchlaufen wenn einer der Button betätigt wurde.
    ;|
    ;|           Das selbe mit dem öffnen der Preferences Datei welche zur sicherheit nochmals kurz geöffnet wird.
    ;|     
  EndIf
  Shared File1$ 
  Shared File2$ 
  Shared File3$ 
  IncludeFile "OpenPreferences.pbi"
EndProcedure
;{<

;}>SecTnineA(21) 

;| == 9       Hapt Anwedungs Program
;|  § 9.1     Hier wird das Haupt Fenster erstellt und die Butten und Grafische Ausgabe der Verzeichnisse
;|            welche im hintergrund Prozess benötigt werden.
;{<

;}>SecTnineB(22) 

;| == 9.2      ButtonHandler Prozedure
;|
;| § 9.2.1   -- Diese Prozedure überprüft welcher Button betätigt wurde und welches Verzeichnis
;|            daraus resultieren als Wert gesetzt werden muss.
;|            Es ist die eihgentlich Abfrage Routine für die Verzeichnisse sowie Dateien.


;- Main Program
OpenWindow(0,100, 100, 500, 400, "Patch my App", #PB_Window_SystemMenu | #PB_Window_ScreenCentered)

XIncludeFile "Open_Create_Preferences.pbi"
;{<

CreateDirectory("Prefs")
;|
;|- Create non.del File
OpenFile(0,GetCurrentDirectory()+"\Prefs\not.del")
CloseFile(0)


;}>SecTnineC(23) 
StringGadget(#Str_Source_DIR, 8,  30, 306, 20, File1$, #PB_String_ReadOnly)   ;- Datei DIR
StringGadget(#Str_Target_DIR, 8,  60, 306, 20, File2$, #PB_String_ReadOnly)   ;- Datei DIR
StringGadget(#Str_Patch_DIR, 8,  90, 306, 20, File3$, #PB_String_ReadOnly)    ;- Datei DIR
                                                                              ;{<

;}>SecTnineD(24) 
;| - Auswahl alte Datei
ButtonGadget(3, 10, 200, 180, 30, "Source File")
BindGadgetEvent(3, @ButtonHandler())

;| - Auswahl neue Datei
ButtonGadget(4, 10, 250, 180, 30, "Target File")
BindGadgetEvent(4, @ButtonHandler())

;| - Auswahl Patch selber
ButtonGadget(5, 10, 300, 180, 30, "Patch File")
BindGadgetEvent(5, @ButtonHandler())
;{<


;}>SecTtenA(25) 
;| == 9.    ButtonHandler Prozedure
;|
;| § 9.1 -- Diese Prozedure überprüft welcher Button betätigt wurde und welches Verzeichnis
;|          daraus resultieren als Wert gesetzt werden muss.
;|          Es ist die eihgentlich Abfrage Routine für die Verzeichnisse sowie Dateien.



Repeat
  Event = WaitWindowEvent()
Until Event = #PB_Event_CloseWindow
;{<

patchmaker:

Code: Alles auswählen

;createpatch(file1.s,file2.s,patchpath.s)
;file1 = Pfad zur alten Version einer Datei
;file2 = Pfad zur neuen Version einer Datei
;Patchpath = Speicherpfad des Patches 

;If OpenPreferences(GetCurrentDirectory()+"\Prefs\myPa.prefs")

;  PreferenceGroup("Files_and_Path")

;    File1$ = ReadPreferenceString ("File_1_used","")
;    File2$ = ReadPreferenceString ("File_2_used","")
;    File3$ = ReadPreferenceString("File_3_used","")
;    
;    ClosePreferences()

; EndIf

Procedure createpatch(File1$,File2$,File3$)
  
  
  Protected MemPoint.l = 0 , LenOfFile1.l , LenOfFile2.l
  Protected ByteOld.b , ByteNew.b
  Protected *Data1, *Data2, *Data3
  
  UseMD5Fingerprint() 
  UseLZMAPacker()
  
  ;Wenn file1 = file2, Prozedure verlassen
  If FileFingerprint(File1$, #PB_Cipher_MD5) = FileFingerprint(File2$,#PB_Cipher_MD5)
    ProcedureReturn #False
  EndIf
  
  ReadFile(0,File1$)
  ReadFile(1,File2$)
  LenOfFile1 = Lof(0)
  LenOfFile2 = Lof(1)
  *Data1 = AllocateMemory(LenOfFile1)
  *Data2 = AllocateMemory(LenOfFile2)
  *Data3 = AllocateMemory(LenOfFile2+33)  ; '+33' für den MD5 Header
  ReadData(0,*Data1,LenOfFile1)
  ReadData(1,*Data2,LenOfFile2)
  
  PokeS(*Data3,FileFingerprint(File1$,#PB_Cipher_MD5)) ; Speichert MD5Fingerprint
  
  While MemPoint < LenOfFile2
    
    If MemPoint < LenOfFile1
      ByteOld = PeekB(*Data1+MemPoint)
    Else
      ByteOld = 0
    EndIf
    
    ByteNew = PeekB(*Data2+MemPoint)
    
    If ByteOld = ByteNew
      PokeB(*Data3+33+MemPoint,0) ;ja nicht den MD5 Header überschreiben
    Else
      PokeB(*Data3+33+MemPoint,ByteOld-ByteNew)
    EndIf
    
    MemPoint = MemPoint + 1
    
  Wend
  
  CreatePack(0,File3$,#PB_PackerPlugin_Lzma ,9) 
  AddPackMemory(0,*Data3,LenOfFile2+33,File2$)
  ClosePack(0)
  CloseFile(0)  ;keine Ahnung wann man am besten file1 u. file2 closed              
  CloseFile(1)
  FreeMemory(*Data1)
  FreeMemory(*Data2)
  FreeMemory(*Data3)
  ProcedureReturn #True
EndProcedure
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Benutzeravatar
Kiffi
Beiträge: 10711
Registriert: 08.09.2004 08:21
Wohnort: Amphibios 9

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von Kiffi »

ChrigiGee hat geschrieben: 10.09.2024 10:01

Code: Alles auswählen

Procedure ButtonHandler()
  If EventGadget() = 3 
    ; [...]
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
  ElseIf EventGadget() = 4
    ; [...]
    
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
  ElseIf EventGadget() = 5          
    ; [...]
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
    
  EndIf
  ;[...]
  IncludeFile "OpenPreferences.pbi"
EndProcedure
CreatePreferences.pbi und OpenPreferences.pbi müssen jeweils nur einmal 'includet' werden. Am besten direkt im oberen Teil Deines Codes.

Siehe: https://www.purebasic.com/german/docume ... ludes.html
a²+b²=mc²
Axolotl
Beiträge: 266
Registriert: 31.12.2008 16:34

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von Axolotl »

Hi ChrigiGee,
ChrigiGee hat geschrieben: 09.09.2024 21:04.....
Was mir aufgefallen ist, bei der erstellten Patch Datei, wird mir leider der komplette Pfad mitgespeichert.
....
Wenn Du dir mein letztes Beispiel angesehen oder evtl. durchgearbeitet hättest, dann würdest Du wissen, dass man in einer Archiv-Datei (Pack, ZIP, etc.) auch einen Filenamen abspeichert. Ich habe in der Procedure folgende Zeile eingebaut.

Code: Alles auswählen

packedFile$ = ReplaceString(NewFile$, #PS$, "?") ; change PathSeparator with some char not allowed in filenames 
Dadurch wird die Datei auf der ersten Ebene gespeichert, weil ich den #PS$ (Path Separator) durch das '?' (Fragezeichen) ersetzt habe. Das Fragezeichen darf ja bekanntlich in Datei- und Verzeichnisnamen nicht verwendet werden.
Alternativ kann man natürlicht auch

Code: Alles auswählen

packedFile$ = GetFilePart(packedFile$) 
schreiben.

Ein paar Gedanken zu deinem Beispiel:
Du hast den Sinn (die Aufgabe) des Befehls IncludeFile "Dateiname" bzw. XIncludeFile "Dateiname" nicht verstanden. Oder anders gesagt, Du verwendest die Befehle falsch. (siehe auch Kommentar Kiffi)

Falls Du die Proceduren aufrufen willst, solltest Du wissen, dass Proceduren direkt aufgerufen werden.
Hier ein ganz einfaches (aus meiner Sicht) Beispiel ergänzt mit verschiedenen Variablen-Deklarationen und deren Auswirkung:
Aber auch dafür hatte ich ja bereits einen Link geschickt, der die Zusammenhänge erklärt.

Code: Alles auswählen

EnableExplicit  ; Variablen müssen deklariert sein, bevor ich sie benutze. 

Global GlobalVar.i = 100      ; Integer Variable, die überall gültig ist. 
Define DefineVar$  = "Leer"   ; String Variable (alternativ: DefineVar.s), die ausserhalb von Procedures gültig ist. 
;                             ;  ... aber mit Shared in Proceduren gültig gemacht werden kann. 
Define ReturnValue ; = 0      ; Interger Variable, weil .i der Standard ist. Initialisiert mit Null ist auch Standard 

Procedure Test(Text$) 
  Protected result  ; Lokale Variable (nur gültig innerhalb der Procedure Test() 
  ;                 ; .... das gilt auch für die Variable Text$
  Shared DefineVar$ ; = "Neuer Wert"  ; direkte zuweisung ist nicht erlaubt !
 
  DefineVar$ = "Neuer Wert"   ; so geht es !! 
  
  Debug "Text als Argument: " + Text$   ; schreibt in die Debug Ausgabe 
  result = 1 
  
  ProcedureReturn result  ; der Wert der lokalen Variable result wird von der Procedure zurückgegeben. 
EndProcedure 

ReturnValue = Test("Hallo Welt!")   ; 

; Debug "result      = " + result          ; Variable result ist hier nicht gültig! Mit EnableExplicit Compilerfehler 
Debug "GlobalVar   = " + GlobalVar 
Debug "DefineVar$  = " + DefineVar$
Debug "ReturnValue = " + ReturnValue       ; PB konvertiert Integer in String (automatisch) 
Debug "ReturnValue = " + Str(ReturnValue)  ; ... so wird die Konvertierung "sauber" durchgeführt. 

DisableExplicit   ; Hebt das Compiler Verhalten EnableExplicit wieder auf. 
Debug "result      = " + result          ; Variable result ist hier gültig, aber 0 weil nicht die gleiche Variable wie in Procedure! 
Using PureBasic latest stable version and current alpha/beta (x64) on Windows 11 Home
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von ChrigiGee »

Hallo Kiffi, (warum will ich Kaffi schreiben)

Ja, ich hab die geh versuche noch drinnen und leider nicht eliminiert.
Ich habe zum Teile nur mit " ; " ausgeklammert zuvor, wenn ich am Werkeln war.

Danke für Deinen Hinweis. Wäre mir wohl noch lange nicht aufgefallen, wie oft sie drinnen sind.
Ich versuche aufzuräumen und hab so den einen oder anderen Fehler auch wieder gefunden, welcher
als erforderlich vermutet eingefügt war und nun herausstellt, dass ich das so nicht benötige.

Ich danke für das mehr Augen Prinzip.

Ich wünsche Dir noch einen schönen Abend.
Christian
Kiffi hat geschrieben: 10.09.2024 10:10
ChrigiGee hat geschrieben: 10.09.2024 10:01

Code: Alles auswählen

Procedure ButtonHandler()
  If EventGadget() = 3 
    ; [...]
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
  ElseIf EventGadget() = 4
    ; [...]
    
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
  ElseIf EventGadget() = 5          
    ; [...]
    IncludeFile  "CreatePreferences.pbi"
    IncludeFile "OpenPreferences.pbi"
    
  EndIf
  ;[...]
  IncludeFile "OpenPreferences.pbi"
EndProcedure
CreatePreferences.pbi und OpenPreferences.pbi müssen jeweils nur einmal 'includet' werden. Am besten direkt im oberen Teil Deines Codes.

Siehe: https://www.purebasic.com/german/docume ... ludes.html
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Benutzeravatar
ChrigiGee
Beiträge: 125
Registriert: 18.07.2024 12:14
Computerausstattung: Lenovo ThinkPad i7, 32GB Ram, 1TB SSD
PB 6.11 LTS, proGUI, IceDesigner
Wohnort: Bern

Re: [PROJEKT] Patch Maker - erstellen Patch File für Anwendungen z.b.

Beitrag von ChrigiGee »

Hallo Axolotl,

die X-Fach vorkommenden Aufrufe waren versuche, die ich erstellte, mit dem gesamten Teil-Projekt
Ich hab sie ausgeklammert, wenn ich versuchte, bei einem anderen Ort. Besser gewesen wäre zu löschen als zu kopieren
und ausklammern zu wollen.

Merke, gerade wie faul ich zum Teile war und nun viel mehr Arbeit drinnen steckt Fehler zu bereinigen.

Ich habe zuerst meine Arbeit hier dokumentiert und erst danach Deine Arbeit begonnen zu ergründen.
Dachte mir, ich möchte versuchen, ob ich es herausbekommen, ansonsten versuche ich meine Gedankenfehler
zu vergleichen mit Deinem Code und Fachwissen.

Merke erst jetzt auch, dass DU eigentlich mir die Lösung, an der ich gescheitert war, bereits präsentiert hättest.
Das war mir so auch nicht bekannt, dass man das Archiv in dem Sinn überlisten kann, mit unerlaubten Zeichen.
Muss ich wohl versuchen, im Hinterkopf zu halten.

Alles in allem hätte ich Dein Beispiel früher zu Hand genommen wäre mir vielleicht sowas aufgefallen
und ich hätte die Bemerkung zum Archiv anders formuliert.

Ich habe gerade ein, zwei Fragen dazu.
Erstellen, wenn ich faul bin aus dem PB heraus bestens geklappt. Muss nicht sein, dass ich es als Anwendung habe.

Erstellen im PB geht, den Patch Anwenden in dem Sinn IN PureBasic geht auch.

Erstelle ich eine Anwendung, passiert bei mir nichts. Ich habe es jetzt mal gepackt mit den verschiedenen Packer Typen.
Einen Test mit Tar als konkretes Beispiel genommen.

Patch ausführen PB geht.
Patch ausführe exe passiert bei mir nichts.

Ich habe es im Verzeichnis der Source gestartet
Ich habe es in einem x-beliebigen Verzeichnis gestartet.

Ich habe die Pfadangaben entfernt und NUR Datei zum Entpacken in dem Sinn auch die "Patch" Datei
in das selber Verzeichnis genommen. Keine Änderung.

Gibt es etwas, auf das man achten müsste oder besser beim Compiler?
Admin Rechte, explizit als non Super User so etwas ...

Sorry für die vielleicht etwas doofe Frage,
ich sehe nur, dass die Anwendung wahrscheinlich beendet wird, ohne richtig aufgeführt zu werden.

Error oder hängen kann ich auch nicht erkennen.

[EDIT]
Da ich mich selber an der Nase nehmen könnte lasse ich den Post.
das ganze ist wieder mal für mich mehr als Peinlich aber ich stehe dazu.

Es steht DEBUG PatchWithPackage(Updater$, OldFile$) oder auch
DEBUG CreatePackage(Updater$, OldFile$, NewFile$)

Wenn man lesen würde oder könnte würde sowas einem an den Kopf springen.

Kopfnuss hätte ich jetz wirklich zusätzlich verdient.
[/EDIT]


Beste Grüsse und einen schönen Feierabend
Christian
Axolotl hat geschrieben: 10.09.2024 14:58 Hi ChrigiGee,
ChrigiGee hat geschrieben: 09.09.2024 21:04.....
Was mir aufgefallen ist, bei der erstellten Patch Datei, wird mir leider der komplette Pfad mitgespeichert.
....
Wenn Du dir mein letztes Beispiel angesehen oder evtl. durchgearbeitet hättest, dann würdest Du wissen, dass man in einer Archiv-Datei (Pack, ZIP, etc.) auch einen Filenamen abspeichert. Ich habe in der Procedure folgende Zeile eingebaut.

Code: Alles auswählen

packedFile$ = ReplaceString(NewFile$, #PS$, "?") ; change PathSeparator with some char not allowed in filenames 
Dadurch wird die Datei auf der ersten Ebene gespeichert, weil ich den #PS$ (Path Separator) durch das '?' (Fragezeichen) ersetzt habe. Das Fragezeichen darf ja bekanntlich in Datei- und Verzeichnisnamen nicht verwendet werden.
Alternativ kann man natürlicht auch

Code: Alles auswählen

packedFile$ = GetFilePart(packedFile$) 
schreiben.

Ein paar Gedanken zu deinem Beispiel:
Du hast den Sinn (die Aufgabe) des Befehls IncludeFile "Dateiname" bzw. XIncludeFile "Dateiname" nicht verstanden. Oder anders gesagt, Du verwendest die Befehle falsch. (siehe auch Kommentar Kiffi)

Falls Du die Proceduren aufrufen willst, solltest Du wissen, dass Proceduren direkt aufgerufen werden.
Hier ein ganz einfaches (aus meiner Sicht) Beispiel ergänzt mit verschiedenen Variablen-Deklarationen und deren Auswirkung:
Aber auch dafür hatte ich ja bereits einen Link geschickt, der die Zusammenhänge erklärt.

Code: Alles auswählen

EnableExplicit  ; Variablen müssen deklariert sein, bevor ich sie benutze. 

Global GlobalVar.i = 100      ; Integer Variable, die überall gültig ist. 
Define DefineVar$  = "Leer"   ; String Variable (alternativ: DefineVar.s), die ausserhalb von Procedures gültig ist. 
;                             ;  ... aber mit Shared in Proceduren gültig gemacht werden kann. 
Define ReturnValue ; = 0      ; Interger Variable, weil .i der Standard ist. Initialisiert mit Null ist auch Standard 

Procedure Test(Text$) 
  Protected result  ; Lokale Variable (nur gültig innerhalb der Procedure Test() 
  ;                 ; .... das gilt auch für die Variable Text$
  Shared DefineVar$ ; = "Neuer Wert"  ; direkte zuweisung ist nicht erlaubt !
 
  DefineVar$ = "Neuer Wert"   ; so geht es !! 
  
  Debug "Text als Argument: " + Text$   ; schreibt in die Debug Ausgabe 
  result = 1 
  
  ProcedureReturn result  ; der Wert der lokalen Variable result wird von der Procedure zurückgegeben. 
EndProcedure 

ReturnValue = Test("Hallo Welt!")   ; 

; Debug "result      = " + result          ; Variable result ist hier nicht gültig! Mit EnableExplicit Compilerfehler 
Debug "GlobalVar   = " + GlobalVar 
Debug "DefineVar$  = " + DefineVar$
Debug "ReturnValue = " + ReturnValue       ; PB konvertiert Integer in String (automatisch) 
Debug "ReturnValue = " + Str(ReturnValue)  ; ... so wird die Konvertierung "sauber" durchgeführt. 

DisableExplicit   ; Hebt das Compiler Verhalten EnableExplicit wieder auf. 
Debug "result      = " + result          ; Variable result ist hier gültig, aber 0 weil nicht die gleiche Variable wie in Procedure! 
Wer nicht fragt, der nichts lernt.
Wer keine Fehler macht, kann sich nicht verbessern.
Das Mysterium, ein wandelndes Lexikon. :mrgreen:

Wer Fragen zu meinem Textstil hat oder sich wundert über mich,
der darf seelenruhig mich direkt ansprechen. Ich beiße noch nicht.
Antworten