Seite 1 von 1

Eigene Registry (XML) für Programm anstatt INI-Dateien

Verfasst: 06.09.2009 18:05
von Thorsten1867
Anstatt mehrerer Preference-Dateien (INI) kann man eine eigene Registry (XML-Datei) für das Programm verwenden.
Die "Registry"-Datei wird beim Programmstart in den Speicher geladen (Open_AppReg) und bei Programmende wieder in die Datei geschrieben (Close_AppReg).
Für den "Key"-Parameter kann auch ein Pfad (vgl. XMLNodeFromPath ) übergeben werden (siehe Beispiel).

Vergleich mit INI-Dateien:
"HKey" entspricht dem Namen der Preference-Datei.
"Key" entspricht "PreferenceGroup"
"Name" entspricht "PreferenceKey" (String)

Code: Alles auswählen

;/ Application Registry
;/ Eigene Registry (XML) anstatt Preferencedateien (INI) für Anwendung verwenden
;/ (c) 2009 by Thorsten Hoeppner

;- Definitionen

Structure AppRegStructure
  id.l
  File.s
EndStructure

;- Tools

Procedure.s XMLDecode(xml$) ; XML-eigene Zeichen ersetzen
  txt$ = ReplaceString(xml$, "&", "&")
  txt$ = ReplaceString(txt$, "<", "<")
  txt$ = ReplaceString(txt$, ">", ">")
  txt$ = ReplaceString(txt$, "&apos;", "'")
  txt$ = ReplaceString(txt$, """, Chr(34))
  txt$ = ReplaceString(txt$, "&#128", "€")
  ProcedureReturn Trim(txt$)
EndProcedure

Procedure.s XMLEncode(txt$) ; XML-eigene Zeichen ersetzen
  xml$ = ReplaceString(txt$, "&", "&")
  xml$ = ReplaceString(xml$, "<", "<")
  xml$ = ReplaceString(xml$, ">", ">")
  xml$ = ReplaceString(xml$, "'", "&apos;")
  xml$ = ReplaceString(xml$, "€", "&#128")
  xml$ = ReplaceString(xml$, Chr(34), """)
  ProcedureReturn xml$
EndProcedure

;- Lade & Speichern der Registry

Procedure.b Open_AppReg(FileName.s="Registry.xml") ; Registry öffnen bzw. neu anlegen
  Protected *Node
  Global AppReg.AppRegStructure
  If FileSize(FileName) > 0 ;{ Registry vorhanden
    AppReg\id = LoadXML(#PB_Any, FileName, #PB_UTF8)
    If XMLStatus(AppReg\id) = #PB_XML_Success
      AppReg\File = FileName
      ProcedureReturn #True
    Else
      AppReg\File = ""
      ProcedureReturn #False
    EndIf ;}
  Else ;{ Neue Registry anlegen
    AppReg\id = CreateXML(#PB_Any, #PB_UTF8)
    If AppReg\id
      *Node = CreateXMLNode(RootXMLNode(AppReg\id))
      If *Node
        SetXMLNodeName(*Node, "Registry") 
         AppReg\File = FileName
      EndIf
      ProcedureReturn #True
    Else
      AppReg\File = ""
      ProcedureReturn #False
    EndIf
  EndIf ;}
EndProcedure

Procedure.b Close_AppReg() ; Registry speichern und schließen
  If IsXML(AppReg\id) And AppReg\File
    If SaveXML(AppReg\id, AppReg\File)
      FreeXML(AppReg\id)
      ProcedureReturn #True
    Else
      FreeXML(AppReg\id)
      ProcedureReturn #False
    EndIf
  ElseIf IsXML(AppReg\id)
    FreeXML(AppReg\id)
    ProcedureReturn #False
  Else
    ProcedureReturn #False 
  EndIf
EndProcedure

Procedure.b Save_AppReg() ; aktuellen Stand sichern
  If IsXML(AppReg\id) And AppReg\File
    If SaveXML(AppReg\id, AppReg\File)
      ProcedureReturn #True
    EndIf
  EndIf
  ProcedureReturn #False 
EndProcedure

;- Abfragen / Schreiben

Procedure.s GetAppRegPath(hKey.s, key.s, Name.s) ; Ermitteln des Pfades für den Node
  If hKey And key
    ProcedureReturn hKey+"/"+ReplaceString(key, "\", "/")+"/"+Name
  ElseIf hKey
    ProcedureReturn hKey+"/"+Name
  ElseIf key
    ProcedureReturn ReplaceString(key, "\", "/")+"/"+Name
  Else
    ProcedureReturn Name
  EndIf
EndProcedure

Procedure Set_AppReg(hKey.s, key.s, Name.s, Value.s) ; Wert in Registry schreiben
  Protected RegPath.s, NodeName.s, *MainNode, *Node
  RegPath = GetAppRegPath(hKey.s, key.s, Name.s)
  If IsXML(AppReg\id) And RegPath
    *MainNode = MainXMLNode(AppReg\id)
    If *MainNode
      *Node = XMLNodeFromPath(*MainNode, RegPath) 
      If Not *Node ;{ Neuen Node erzeugen
        *LastNode = *MainNode
        For n = 1 To CountString(RegPath, "/")+1
          NodeName = StringField(RegPath, n, "/")
          *Node = XMLNodeFromPath(*LastNode, NodeName)
          If Not *Node
            *Node = CreateXMLNode(*LastNode, -1)
            If *Node
              SetXMLNodeName(*Node, NodeName)
              *LastNode = *Node
            EndIf
          Else
            *LastNode = *Node
          EndIf
        Next
      EndIf ;}
      If *Node ; Wert für Node setzen
        SetXMLNodeText(*Node, XMLEncode(Value))
      EndIf
    EndIf
  EndIf
EndProcedure

Procedure.s Get_AppReg(hKey.s, key.s, Name.s, DefaultValue.s="") ; Wert aus Registry auslesen
  Protected *MainNode, *Node, RegPath.s
  RegPath = GetAppRegPath(hKey.s, key.s, Name.s)
  If IsXML(AppReg\id)
    *MainNode = MainXMLNode(AppReg\id)
    If *MainNode
      *Node = XMLNodeFromPath(*MainNode, RegPath)
      If *Node
        ProcedureReturn XMLDecode(GetXMLNodeText(*Node))
      EndIf
    EndIf
  EndIf
  ProcedureReturn DefaultValue
EndProcedure


;- Beispiel

Open_AppReg("E:\Temp\Test.xml") ; Programmstart

; Einträge in Registry

Set_AppReg("Einstellungen", "Adresse", "Name", "Thorsten Hoeppner")
Set_AppReg("Einstellungen", "Adresse", "Straße", "Alte Zeile 67")
Set_AppReg("Einstellungen", "Adresse", "Ort", "87600 Buron")
Set_AppReg("Einstellungen", "Adresse/Telefon", "Privat", "09876-12345")
Set_AppReg("Einstellungen", "Adresse/Telefon", "Büro", "09876-54321")

Set_AppReg("Dateien", "Programm", "Name", "Test.exe")
Set_AppReg("Dateien", "Daten", "Datenbank", "Test.db")
Set_AppReg("Dateien", "Daten", "Text01", "Test.doc")
Set_AppReg("Dateien", "Daten", "Text01", "Test.rtf")

; Auslesen aus Registry

Debug "Name: " + Get_AppReg("Einstellungen", "Adresse", "Name")
Debug "Telefon (Privat): " + Get_AppReg("Einstellungen", "Adresse", "Name")
Debug "Programmdatei: "+Get_AppReg("Dateien", "Programm", "Name")
Debug "3. Textdatei: "+Get_AppReg("Dateien", "Daten", "Text03", "* nicht vorhanden *")

Close_AppReg() ; Programmende

Verfasst: 06.09.2009 18:16
von ts-soft
:allright:
Nette Idee

Aber wenn man ansonsten kein XML benötigt macht es die Exe nur unnötig
groß, worauf man eigentlich auch sch**ssen kann :wink:

Warum Du "Procedure.b" verwendest wird sich mir wohl nie erschliessen :mrgreen:

Gruß

Thomas

Verfasst: 06.09.2009 18:59
von Thorsten1867
Für kleinere Projecte, wo man nur ein paar Einstellungen laden muss ist eine INI-Datei sicher sinvoller.

Aber bei mehreren INI-Dateien und vor allem, wenn man die Einstellungen präsent haben möchte, ohne jedes Mal die INI-Datei zu öffnen ist eine "Registry" sicher sinnvoll. Einen großen Vorteil sehe ich auch darin, dass ich nicht jede Änderung der Einstellungen usw. einzeln wieder in die Datei schreiben muss.

Verfasst: 08.09.2009 10:47
von Kai
Sehr schöne Idee. :allright: