BDE (Borland Database Engine) auslesen

  • Hallo zusammen!
    Ich würde gerne aus der BDE die Definitionen eines Datenbank-Aliases auslesen. In Delphi gibt's die Funktionen GetAlias...
    Sowas ähnliches suche ich für AutoIT. Hab im Forum und bei Google nix passendes gefunden.
    Diese Definitionen sind in der Datei IDAPI32.CFG gespeichert. Mit der Funktion REGREAD kann ich den Pfad dieser Datei finden.
    Leider ist die binär gespeichert.
    Mir kommt es dabei hauptsächlich auf die Einträge "Langdriver" und "Server Name" an.

    Hat jemand eine Idee?

    Vorab schon mal vielen Dank für die Antworten.
    Gruß
    TinkyWinky

    P.S.: bin noch im Anfängerstadium, deshalb bitte ich um verständliche Antworten. Danke. ;)

    • Offizieller Beitrag

    Im Schlüssel
    "HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine\Settings\DRIVERS"
    findest du die Aliases als Unterschlüssel im Klartext.
    Zu jedem Unterschlüssel kannst du dann (sofern registriert) 'Langdriver' und 'Servername' auslesen.

    z.B. "INTRBASE"
    Key: "HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine\Settings\DRIVERS\INTRBASE"
    SubKey: "..\DB OPEN" und "INIT"
    Die Informationen sind in einem/beiden der SubKeys enthalten.
    Hier sind sie in: "..\DB OPEN"
    LANGDRIVER = DBWINWE0
    SERVER NAME = IB_SERVER:/PATH/DATABASE.GDB

    Edit:
    So kannst du die IDAPI32.CFG in Klartext wandeln:
    - noch etwas erweitert, nun werden zusammengehörige Daten etwas gruppiert

    Noch ein Edit: :D
    Ich empfehle dir aber die Registry auszulesen, da die IDAPI32.CFG z.B. die Langdriver nicht angibt, obwohl das Feld dafür vorgesehen ist.

    Spoiler anzeigen
    [autoit]

    $path = 'C:\GDILine\BDE\idapi32.cfg'
    $fh = FileOpen($path, 16)
    $read = StringTrimLeft(FileRead($fh), 2)
    FileClose($fh)
    $text = ''
    For $i = 1 to StringLen($read)-2 Step 2
    $tmp = Dec(StringMid($read, $i, 2))
    Switch $tmp
    Case 0
    $tmp = 32
    Case 1,2,3,4
    ContinueLoop
    EndSwitch
    $text &= Chr($tmp)
    Next
    $ar_text = StringSplit($text, 'TYPE', 1)

    [/autoit] [autoit][/autoit] [autoit]

    Local $a_BDE[UBound($ar_text)-2][2]
    For $i = 2 To UBound($ar_text) -1
    $ar_text[$i] = StringReplace($ar_text[$i], ' ', '***', 1, 1)
    $tmp = StringSplit($ar_text[$i], '***', 1)
    $a_BDE[$i-2][0] = $tmp[1]
    $a_BDE[$i-2][1] = $tmp[2]
    $tmp = StringSplit($a_BDE[$i-2][1], ' ', 1)
    If @error Then ContinueLoop
    ConsoleWrite('==========' & $a_BDE[$i-2][0] & '==========' & @CRLF)
    For $j = 1 To UBound($tmp) -1
    ConsoleWrite($tmp[$j] & @CRLF)
    Next
    Next

    [/autoit]
  • Hallo BugFix,
    vielen Dank für Deine schnelle Antwort.
    Leider ist die Reg. ungeeignet, da dort nur die Standard-Vorgaben für Aliase hinterlegt sind.
    Es geht kein Weg an der IDAPI32.CFG vorbei.

    Dein Script hat mir 'ne Menge zu denken gegeben:
    - zuerst wird die IDAPI32.CFG binär geöffnet
    - dann werden die Zahlen in ASCII umgewandelt
    - anschließend wird der Text in Arrays aufgeteilt (jeweils nach dem Trennzeichen 'TYPE')
    soweit hab ich's verstanden. Was dann folgt ist mir zu hoch.
    Leider ist der Suchstring 'TYPE' auch ungeeignet, da bereits mitten aus den Informationen zu einem Alias enthalten.

    Ich bastel nun schon 'ne Weile an einer Lösung; krieg's aber nicht hin.
    Ich habe in meiner IDAPI32.CFG über 90 Datenbank-Aliase. Leider sind zu jedem Alias unterschiedliche Informationen gespeichert.
    Der Text vor der Bezeichnung 'DB INFO' ist auf jeden Fall der Alias-Name. Leider ist die Zeichenlänge nicht immer gleich lang.
    Die Arrays müssten so gefüllt werden, dass sie mit dem Alias-Namen beginnen.
    Wie geht das, wenn ich nicht nach einem einheitlichen Text suchen kann?
    Allerdings habe ich festgestellt, dass vor dem Alias-Namen immer mindestens 6 Leerzeichen stehen und dahinter immer 5 Leerzeichen (gefolgt von dem Text 'DB INFO').
    Vielleicht kannst Du mir nochmal einen Tipp geben.

    MfG
    TinkyWinky

    Einmal editiert, zuletzt von TinkyWinky (15. Oktober 2009 um 22:41)

    • Offizieller Beitrag

    Ja, die IDAPI32.CFG ist schon eklig.
    Ich hab das mit den mir vorliegenden cfg's getestet. Bei denen waren zumindest logische Gruppierungen immer ab 'TYPE'.
    Intern ist auch kein Konzept ersichtlich. Die (Nicht-Text-) Zeichen 01, 02, 03, 04 überspringe ich, da sonst eine Textausgabe nicht möglich wär. Das sind u.A. Markierungen für Start of Text / End of Text - aber ohne logisch erkennbare Zusammenhänge zu den einzelnen Aliases.

    Wenn du bei dir konstante Längen zwischen den Elementen findest, kannst du diese zum Splitten verwenden. Eine andere Möglichkeit sehe ich nicht.
    Ich habe um Splitten zu können die ersten 3 Leerzeichen im String gebraucht (Alias-3 Leerzeichen-Restinfo). Da aber auch größere Lücken im String sind, würde mit StringSplit an allen diesen Stellen gesplittet werden. Somit habe ich StringReplace genutzt, da ich dort festlegen kann, dass nur das erste Vorkommen eines Strings verwendet wird. Also habe ich 3 Leerzeichen durch 3 Sternchen ersetzt und dann an den Sternchen gesplittet. ;)

  • OK, vielen Dank.
    Die einzigen Konstanten sind die 6 Leerzeichen vor und 5 Leerzeichen hinter dem Aliasnamen.
    Damit versuch ich's morgen nochmal. Ich krieg heute nix mehr auf die Reihe und geh ins Bett.

  • Hallo und guten Abend,

    ich bin nun ein Stück weiter gekommen.
    Die einzelnen Aliase werden nun korrekt in Arrays aufgeteilt (die letzten 4 Arrays sind überflüssig).
    Jedenfalls funktioniert's bei mir so. Habe leider keine Vergleichs-CFGs, daher kann ich's nur für mich behaupten.

    [autoit]

    #include<array.au3>
    $path = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Borland\Database Engine", "CONFIGFILE01") ; Pfad der IDAPI32.CFG wird aus Registry ausgelesen
    $fh = FileOpen($path, 16) ; IDAPI32.CFG wird binär geöffnet
    $read = StringTrimLeft(FileRead($fh), 2) ; Inhalt wird eingelesen
    FileClose($fh) ; IDAPI32.CFG wird geschlossen
    $text = '' ; Text-Variable wird initiiert
    For $i = 1 to StringLen($read)-2 Step 2 ; vom ersten bis zum letzten Zeichen wird der eingelesene Binärcode durchlaufen
    $tmp = Dec(StringMid($read, $i, 2)) ; und jedes Hexcode-Zeichen wird in seine dezimale Entsprechung umgewandelt
    Switch $tmp
    Case 0 ; Code 0 wird in ein Leerzeichen umgewandelt
    $tmp = 32
    Case 1 ; Code 1 (Start of header) wird übergangen
    ContinueLoop
    case 2 ; Code 2 (Start of text) wird in ein at umgewandelt
    $tmp = 64
    case 3, 4 ; Code 3 (End of text) und Code 4 (End of transmission) wird übergangen
    ContinueLoop
    EndSwitch
    $text &= Chr($tmp) ; mit jeder Schleife wir die Variable um ein weiteres ASCII-Zeichen ergänzt
    Next

    [/autoit][autoit][/autoit][autoit]

    $text = StringReplace($text," DATABASES ","",1) ; führender Text wird abgeschnitten

    [/autoit][autoit][/autoit][autoit]

    $arraytext = StringSplit($text, '@ @', 1) ; die lange Textvariable wird in Arrays gesplittet (und zwar an der Stelle an der zwei at mit einem Leerzeichen dazwischen stehen)

    [/autoit][autoit][/autoit][autoit]

    _ArrayDisplay($arraytext)

    [/autoit]

    Jetzt zwei weitere Fragen:
    1. bei mir passen immer zwei Aliase zusammen, die jeweils auf den gleichen Namen enden (z.B. Test1-muster, Test2-muster).
    Wie finde ich die beiden(!) Arrays (_ArraySearch), die z.B. den Zusatz -muster enthalten?
    2. Wenn ich die Arrays dann kenne, - wie filtere ich den Text zwischen "Server Name" und "User Name" heraus?
    Das ist nämlich der anfangs gesuchte Pfad für die Datenbanken.

    Wäre dankbar, für eine weitere Hilfe.

    Gruß
    TinkyWinky

    Edit:
    Ok, ich habe die Funktion _StringBetween gefunden, mit der die zweite Frage geklärt wäre :)
    Die erste Frage bleibt allerdings offen.

  • Hallo progandy,

    danke für den Link, aber im Prinzip habe ich ja bereits die Trennung der einzelnen Blöcke in der IDAPI32 gefunden.
    Ich hab's halt nur durch zwei aufeinenderfolgende @ sichtbar gemacht.

    Aber mit Arrays (wie von BugFix angeregt) stehe ich noch auf Kriegsfuß. Wie durchsuche ich den Inhalt
    und finde die beiden gesuchten Einträge?

    Gruß
    TinkyWinky

    • Offizieller Beitrag

    Ich hab mal progandys Hinweis eingearbeitet. Das ergibt dann schonmal eine saubere Übersicht.
    Da meine CFG sich deutlich von deiner unterscheidet, mußt du die weitere Bearbeitung individuell vornehmen. Meine Ansätze treffen bei dir nicht zu.

    Spoiler anzeigen
    [autoit]

    $path = 'C:\GDILine\BDE\idapi32.cfg'
    $path = '..\BDE\idapi32.cfg'
    $fh = FileOpen($path, 16)
    $read = StringTrimLeft(FileRead($fh), 2)
    FileClose($fh)
    $text = ''
    For $i = 1 to StringLen($read)-2 Step 2
    $tmp = Dec(StringMid($read, $i, 2))
    Switch $tmp
    Case 0, 1
    $tmp = 32 ; Leerzeichen
    Case 2
    ContinueLoop
    Case 3
    $tmp = 13 ; Zeilenumbruch
    Case 4
    $tmp = 61 ; =
    EndSwitch
    $text &= Chr($tmp)
    Next
    ConsoleWrite($text & @CRLF)

    [/autoit]


    So sieht es z.B. bei mir aus:

    Spoiler anzeigen
  • Herzlichen Dank, Leute. Besonders an BugFix!
    Ich hab heute 'ne Menge gelernt und bin so richtig auf den Geschmack gekommen, mit AutoIT weitere Projekte zu starten.
    Eure Hilfe war echt super und vor allem so unglaublich schnell.
    Ich denke, ich werde öfter mal vorbeischauen.

    Gruß
    TinkyWinky

  • So, ich habe mich auch dran versucht und kann jetzt in eine Ini konvertieren ;)

    Spoiler anzeigen
    [autoit]


    Const $cSeparate = Chr(0)
    Const $cParam = Chr(1)
    Const $cEndBlock = Chr(2)
    Const $cNewEntry = Chr(3)
    Const $cEquality = Chr(4)

    [/autoit] [autoit][/autoit] [autoit]

    Func _IDAPI32_IniConvert($sIDAPI32file, $ININame)
    Local $sIDAPI32 = FileRead($sIDAPI32file)
    Local $aIDAPI32_Blocks = StringSplit($sIDAPI32, $cEndBlock)
    FileDelete($ININame)
    For $i = 1 To $aIDAPI32_Blocks[0]
    If StringLeft($aIDAPI32_Blocks[$i],1) = $cNewEntry Then $aIDAPI32_Blocks[$i] = StringTrimLeft($aIDAPI32_Blocks[$i],1)
    __IDAPI32_ParseBlock($aIDAPI32_Blocks[$i], $ININame)
    Next
    Return FileExists($ININame)
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    Func __IDAPI32_ParseBlock(ByRef $Block, $ININame)
    $Block = StringSplit($Block, $cNewEntry)
    Local $Entry
    Local $INI_Section=''
    For $i = 1 To $Block[0]
    $Entry = StringSplit($Block[$i], $cSeparate)
    If $Entry[0] <> 6 Then ContinueLoop ; nur wenn 7 Felder vorhanden weitermachen
    If ($Entry[1]&$Entry[2]&$Entry[3])='' And $Entry[5]=$cParam Then
    $INI_Section &= '_'&$Entry[4]
    ElseIf $Entry[2] = $cParam And $Entry[4] = $cEquality Then
    If StringLeft($INI_Section,1)='_' Then $INI_Section=StringTrimLeft($INI_Section,1)
    IniWrite($ININame, $INI_Section, $Entry[3], $Entry[5])
    EndIf
    Next
    EndFunc

    [/autoit] [autoit][/autoit] [autoit]

    _IDAPI32_IniConvert(@DesktopDir & "\IDAPI32.cfg", @DesktopDir & "\IDAPI32.ini")

    [/autoit]


    Die SectionNames setzen sioch wie folgt zusammen:
    Es gibt ja am Anfang jeden Blocks Zeilen, die kein Equality / Gleichheitszeichen beinhalten. Diese werden einfach mit einem Unterstrich aneinandergehängt.
    Beispiel:

    Code
    . [[ZEILE NUR WEGEN FORMATIERUNG]]
       DRIVERS   
       PARADOX   
       INIT   
       NET DIR = C:\


    Wird zu

    Code
    [DRIVERS_PARADOX_INIT]
    NET DIR=C:\