Gemischte Ini-Datei updaten - Ideen gesucht

  • Ok, durch unsere Diskussion (das war das Ziel dieses Threads) ist mir das Ziel nun klarer geworden. Kürzer formuliert sähe es nun so aus:

    Neue Namen: Soll.ini = Master.ini; Ist.ini = User.ini; Ergebnis.ini = Merged.ini - "Ini" ist hierbei sinnbildlich zu verstehen, es sind nicht zwingend Dateien auf der Festplatte, sondern können auch nur im RAM existieren.

    • Die Master.ini wird zunächst 1:1 in die Merged.ini kopiert.
    • Dann werden alle Schlüssel-Werte in der Merged.ini durch die in der User.ini ersetzt.
    • User.ini und Merged.ini werden miteinander verglichen und falls es auch nur 1 Unterschied gibt, wird der Inhalt der User.ini durch den Inhalt der Merged.ini ersetzt.
    • Als unterschiedlich wird gesehen, wenn die Inhalte nicht 1:1 stimmen, inkl. Groß- / Kleinschreibung.

    Somit könnte man einfach alle Schlüssel und -Werte der User.ini in ein Dictonary laden, z.B. mit AspirinJunkies Code. Dann braucht man nur noch die Merged.ini zu durchlaufen und alle Schlüsselwerte zu prüfen, ob sie im Dictionary exitieren. Falls ja, wird der Schlüssel-Wert in der Merged.ini mit dem aus dem Dict ersetzt.

    Am Schluss, wie gesagt, die Merged.ini mit der User.ini vergleichen, ob sie unterschiedlich sind und bei Bedarf in die User.ini schreiben.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Die ganze Zeit habe ich mich gefragt, warum der Code die Sektionen einzeln einliest, statt eine ganze Ini in einem Rutsch. :/ Nun weiß ich es.

    Leider hatte ich diese Erkenntnis erst, nachdem ich den Code so umgeschrieben hatte, dass er eine ganze Ini eingelesen hat. :whistling: Der Grund für das sektionsweise Einlesen ist ein ganz einfacher: In verschiedenen Sektionen können durchaus die gleichen Schlüssel vorkommen, insbesondere bei Sprach-Inis.

    Ist das richtig, oder gibt es noch einen anderen Grund für das sektionsweise einlesen?

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • AspirinJunkie

    In manchen Inis kann man sowas wie einen Kommentar bzw. eine Erläuterung hinter den Sektionsnamen schreiben, z.B.:

    [Config EN] - for english main program

    ; ColorSchemes 2020-07-19: White_Black_Red, Gray_White_Blue, auto

    ColorScheme=auto

    ProjPanel.RememberVisibility=1

    ProjPanel.RememberBlaBla=1

    ProjPanel_RememberFoo=1

    Dann wird die Sektion nicht gefunden. Ist es viel Aufwand, den Code so erweitern, dass er auch damit zurechtkommt? Das ist jetzt nichts, was wirklich benötigt wird, aber falls es nicht viel Aufwand macht, ... 8)

    Hier mein Versuch. Es funktioniert zwar, aber das war eher ein Raten, als Wissen, das könnte also wer-weiß-was an Nebenwirkungen haben, z.B. den Code verlangsamen oder so. Kannst du mal drüber gucken?

    AutoIt
    Func _IniReadSection($sFilePath, $sSection, Const $bDic = False)
    
        ...
    
        ; Section komplett als String auslesen
    ;     Local $aSectionRaw = StringRegExp($sFile, '(?m)^\[' & _RegExEscape($sSection) & '\]\s*\R([^\[]+)', 1)
        Local $aSectionRaw = StringRegExp($sFile, '(?m)^\[' & _RegExEscape($sSection) & '\]\s*([^\[]+)', 1) ; <== hier mein Versuch
        If @error Then Return SetError(2, @error, False)

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • In manchen Inis kann man sowas wie einen Kommentar bzw. eine Erläuterung hinter den Sektionsnamen schreiben, z.B.:


    [Config EN] - for english main program

    ; ColorSchemes 2020-07-19: White_Black_Red, Gray_White_Blue, auto

    ColorScheme=auto

    Dann wird die Sektion nicht gefunden.

    AutoIt richtet sich streng nach der WinAPI (in der Hilfe wird von "standardkonform" geschrieben) !

    Auszug aus : https://de.wikipedia.org/wiki/Initialisierungsdatei

    Beim Erstellen einer INI-Datei sind folgende Regeln zu beachten:

    • Jede Sektion darf nur einmal vorkommen.
    • Jeder Schlüssel darf nur einmal je Sektion vorkommen. Auf Werte wird mittels Sektion und Schlüssel zugegriffen.
    • Kommentare werden mit einem ";" eingeleitet.
    • Kommentare dürfen nur auf separaten Zeilen (nicht hinter Sektionsüberschriften oder Schlüsseln) stehen.
    • Leerzeichen und Anführungszeichen werden von verschiedenen Programmen teilweise unterschiedlich behandelt.

    Ich habe aber auch häufiger .ini-Dateien gesehen, bei denen diese Regeln (offenbar vom jeweiligen Softwarehersteller) erweitert wurden, z.B.

    • Kommentare hinter [Sektionen] und Schlüsseln sind möglich
    • Werte-Schlüsselpaare können alleinstehend, d.h. ohne [Sektion] angegeben werden. Das ist bei den AutoIt-Funktionen IniRead und IniReadSection ja nicht möglich, da die Angabe einer [Sektion] verpflichtend ist

    Vermutlich wurde hierfür ein eigener INI-Parser erstellt. So habe ich das z.B. für meine Inno-Setup Skripte jedenfalls gemacht.

    86598-musashi-c64-png

    "Am Anfang wurde das Universum erschaffen. Das machte viele Leute sehr wütend und wurde allenthalben als Schritt in die falsche Richtung angesehen."

  • In verschiedenen Sektionen können durchaus die gleichen Schlüssel vorkommen, insbesondere bei Sprach-Inis.


    Ist das richtig, oder gibt es noch einen anderen Grund für das sektionsweise einlesen?

    Dann würde man ja alle Key-Values in ein einziges Dictionary schmeißen.
    Will man die ganze Ini in einer AutoIt-Struktur muss diese hingegen entsprechend verschachtelt sein.
    Sinnvoll: Ein Dictionary mit Section-Names als Key und dem Key-Value-Dictionary der Sektion als Value.

    Ich hatte das sectionweise gemacht weil ich so wirklich nur die Werte auswerten wollte die auch tatsächlich gebraucht werden.
    Kann man aber natürlich auch einfach umbauen (siehe unten).

    Zum Thema Unterschiede detektieren: So wie du es schreibst reicht es einen Stringvergleich (wie in Post 58) zu machen.

    Hier noch die Variante mit dem Text hinter den Section-Header und der ganzen Ini in einer AutoIt-Struktur:

  • Zum Thema Unterschiede detektieren: So wie du es schreibst reicht es einen Stringvergleich (wie in Post 58) zu machen.

    Gute Idee, mit dem @extended. Ich hatte eine zusätzliche ByRef Variable eingebaut, was auch funktioniert, deine Idee finde ich allerdings viel eleganter und werde sie einbauen.

    Hier noch die Variante mit dem Text hinter den Section-Header und der ganzen Ini in einer AutoIt-Struktur:

    Nachdem mir nun klar wurde, dass beim Ganze-Ini-Einlesen alle Schlüssel in ein Dict geschmissen würden und evtl. überschrieben würden, finde ich sektionsweises Einlesen richtig gut! :thumbup:Trotzdem danke für den Code zum Einlesen der ganzen Ini. Und ganz besonderen Dank für das RegEx Pattern für Sektions-Header mit Text dahinter. Es ist einfach ein gutes Gefühl, wenn du die Pattern machst! :rock:

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Um also einen Stringvergleich mit einzubauen muss man nur die Return-Zeile ändern zu: Return SetExtended($sRet <> $sIst, $sRet)

    Dann kann man mit @extended prüfen ob es eine Änderung gab oder eben nicht.

    Ich habs jetzt übernommen als Return SetExtended(Not ($sRet == $sIst), $sRet), damit auch Unterschiede in Groß-/Kleinschreibung festgestellt werden.

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Trotzdem möchte ich nochmal einwerfen, dass es doch grundsätzlich wumpe ist, ob die Einträge in den Usereinstellungen sich von den Standardeinstellungen unterscheiden.
    Darauf muss ich doch nicht prüfen! Jeder Vergleich kostet mehr Zeit als das simple Einlesen von Werten.

    - 2 Dateien existieren (System- und Usereinstellungen)

    - Einlesen der Systemdatei in Laufzeitvariable (Dictionary ist hier wohl der beste Weg)

    - Einlesen der Userdatei ins Dictionary (wobei automatisch die Systemdaten überschrieben werden)

    Dann kümmert es dich nicht die Bohne ob und was der User wann, wie, weshalb, warum geändert hat. - Seine Änderungen haben Priorität und werden immer übernommen.

  • Trotzdem möchte ich nochmal einwerfen,

    Genau darum geht es in diesem Thread, :) es sollen Ideen gesammelt und diskutiert werden. Also vielen Dank fürs "Einwerfen"! :thumbup:

    Systemdatei, Systemeinstellung, Systemdaten, ... da stelle ich mir was vor, was hier nicht gemeint ist. Eher sehe ich es als ein 2-Dateien Konzept, bei dem Einstellungen in eine Global- und eine User-Datei gespeichert werden. Ich gebe dem Kind den Namen "Global/User-Konzept" (das schreibt sich auch leichter). :saint:

    Auch wenn (glaube ich) sonst niemand etwas zum 2-Dateien Konzept gesagt hat, ich finde es gut. :) Für den Moment werde ich zwar das 1-Dateien Konzept benutzen, weil ich einfach nicht riskieren will, was alles schief gehen kann, wenn ich so viele Stellen im Code ändern würde. Aber später könnte das durchaus umgestellt werden.

    Wie sieht es denn aus, wenn ein Programm das Global/User Konzept und einen Settings-Dialog benutzt (SciTE mach das doch so, oder?), werden dann die Einstellungen vom Settings-Dialog in der User-Datei gespeichert? - Hmm, ... :/... jetzt wo ichs schreibe, kann ich es mir kaum anders vorstellen. Ok, ist klar. War also keine Frage, sondern laut gedacht.

    Was gibt es denn an Nachteilen bei dem 2-Dateien-Konzept gegenüber dem mit nur 1 Datei? Wo Licht ist, muss es doch auch Schaten geben. 8o

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    • Offizieller Beitrag

    Was gibt es denn an Nachteilen bei dem 2-Dateien-Konzept gegenüber dem mit nur 1 Datei?

    Keine - nur Vorteile.

    Du brauchst nur die Globale Datei pflegen, was der User macht (und ob er überhaupt was macht) ist absolut egal.

    Und für den Fall, dass du irgendwann auch mal projektorientierte Einstellungen vornehmen willst, gehst du mit deinem 1-Datei System Wasser saufen.

    Global und User würdest du einfach um eine Datei im Objektordner erweitern, die wiederum evtl. abweichende Werte aus der Userdatei überschreibt.

  • ... projektorientierte Einstellungen vornehmen ...

    Global und User würdest du einfach um eine Datei im Objektordner erweitern, die wiederum evtl. abweichende Werte aus der Userdatei überschreibt.

    Was meinst du denn mit projektorientierte Einstellungen und Objektordner? :/

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

  • Dem (bezogen auf Post #68 von BugFix) kann ich nur zustimmen! Die einfachsten Lösungen sind immer die besten :)

    • Offizieller Beitrag

    Was meinst du denn mit projektorientierte Einstellungen und Objektordner?

    Objekt sollte Projekt heißen, Scheiß Autokorrektur am Handy. :D

    Wenn du ein Projekt erstellst, wirst du alle zugehörigen Dateien (au3, Ini, ico, etc.) in einem gemeinsamen Ordner speichern - dem Projektordner.

    Nun kann es sein, dass du für dieses Projekt eine bestimmte Editorkonfiguration möchtest. Das kannst du dann mit einer Einstellungsdatei in diesem Ordner regeln. Deren Inhalt hat Vorrang gegenüber den User-Einstellungen.

    Was ich gerade nicht weiß: Erkennt PSPad den Wechsel auf ein anderes Editor Tab? - Dieses "OnChange" Ereignis ist erforderlich, um dann die Einstellungen on-the-fly zu aktualisieren.

  • Projektordner.

    Nun kann es sein, dass du für dieses Projekt eine bestimmte Editorkonfiguration möchtest. Das kannst du dann mit einer Einstellungsdatei in diesem Ordner regeln. Deren Inhalt hat Vorrang gegenüber den User-Einstellungen.

    In Pau3 liegt die User-Ini im Projektordner. :D

    Was du beschreibst kommt mir bekannt vor von SciTE. Interessantes Konzept und recht flexible flexibel. (Scheiß Nicht-Autokorrektur am PC). 8o

    Was ich gerade nicht weiß: Erkennt PSPad den Wechsel auf ein anderes Editor Tab? - Dieses "OnChange" Ereignis ist erforderlich, um dann die Einstellungen on-the-fly zu aktualisieren.

    Ich weiß gerade nicht mehr wer, aber vor kurzem hat das jemand schön formuliert, etwas mit PSPad und "hartes Brot!". Und das ist wahr! - PSPad erkennt vieles, auch Editor-Tab Wechsel. (Edit: Z.B. wird beim Tab Wechsel der CodeExplorer automatisch aktualisiert.) ... Leider gibt PSPad kein einziges Ereignis an Entwickler von Add-ons weiter. Keine Chance. :(

    Das ist einer der Hauptgründe, weshalb ich langsam anfange mit SciTE zu liebäugeln. ;) Wenn mir jemand für SciTE "mal eben so nebenbei" ein fertiges Grundgerüst zur Verfügung stellen würde, mit dem man den SciTE4AutoIt3 Editor in eine eigene MDI Umgebung einbinden könnte, würde ich wahrscheinlch sofort wechseln und SciTE mit all dem Komfort aufpeppen, den die eingefleischen SciTE Nutzer "nicht brauchen". :P

    Wenn jemand sagt: "Das geht nicht!" Denke daran: Das sind seine Grenzen, nicht deine.

    2 Mal editiert, zuletzt von Professor Bernd (25. April 2021 um 22:57)