[UDF] *.reg Parser

  • Vllt kanns mal jemand brauchen, ein Parser der eine *.reg Datei auswertet.
    Würde mich freuen wenns auch mal jemand testen könnte, vllt hab ich ja einen Fehler übersehen.
    Noch mehr würde ich mich freuen wenn jemand weiß wie man den Redim Befehl sparen könnte, ich fürchte der macht die Sache schon wirklich langsam :(

    Spoiler anzeigen
    [autoit]

    ;##########################################################################################
    ;# *.reg Parser
    ;#
    ;# Parameter: $RegFile Pfad + Dateiname zu einer *.reg Datei
    ;#
    ;# Rückgabe: Gibt ein Array in folgendem Format zurück:
    ;# [0][0] Anzahl der n-Einträge, -1 falls die reg-Datei nicht geöffnet werden konnte
    ;# [n][0] Aktion, "ADD" zum Hinzufgen/Ändern eines Schlüssels/Wertes; "DEL" zum Entfernen
    ;# [n][1] Hauptschlüssel: "HKCR", "HKCU", "HKLM", "HKU", "HKCC"
    ;# [n][2] Unterschlüssel
    ;# [n][3] Typ: REG_DWORD, REG_BINARY, REG_SZ, REG_MULTI_SZ, REG_EXPAND_SZ
    ;# [n][4] Wert; "(DEFAULT)" für Standard
    ;# [n][5] Daten
    ;#
    ;# Autor: Bitboy
    ;# WWW: autoit.de
    ;###########################################################################################

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

    Func _RegParse($RegFile)
    Local $LineRead, $Action, $MainKey, $SubKey, $Type, $Value, $Data, $tmpKey, $retArr[2], $Counter, $LineCounter
    $Counter = 0
    $OpenReg = FileOpen($RegFile, 0)
    ;Zeilen der Datei zählen und Arraygröße entsprechend setzen
    $LineCounter = _IMPFileCountLines($RegFile)
    Redim $retArr[$LineCounter][6]

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

    ;Fehler beim öffnen der Datei
    If $OpenReg = -1 Then
    $retArr[0][0] = -1
    Return $retArr
    EndIf

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

    ;Zeile "Windows Registry Editor Version 5.00" überspringen
    $LineRead = FileReadLine($OpenReg)
    While 1
    $LineRead = FileReadLine($OpenReg)
    If @error Then ExitLoop
    If $LineRead <> "" Then
    $Counter = $Counter + 1
    EndIf

    ;Variablen zurücksetzen
    $Action = ""
    $Type = ""
    $Value = ""
    $Data = ""

    ;Schlüssel ermitteln
    If StringLeft($LineRead,1) = "[" And StringRight($LineRead,1) = "]" Then
    ;Hauptschlüssel und Unterschlüssel trennen
    ;Klammer entfernen
    $tmpKey = StringMid($LineRead,2,StringLen($LineRead)-2)
    $MainKey = StringLeft($tmpKey,StringInStr($tmpKey, "\")-1)
    $SubKey = StringRight($tmpKey, StringLen($tmpKey) - StringLen($MainKey))
    ;MsgBox(0,"test",$SubKey)
    ;Aktion ermitteln: Wenn ein - Zeichen an 2.Stelle steht wird der Schlüssel gelöscht
    If StringMid($LineRead,2,1) = "-" Then
    $Action = "DEL"
    ;$Counter = $Counter + 1
    Else
    $Action = "ADD"
    EndIf

    ;Werte, Daten, Typ und Aktion ermitteln
    ElseIf StringInStr($LineRead,"=") Then
    ;$Counter = $Counter + 1
    $Value = StringLeft($LineRead, StringInStr($LineRead,"=") - 1)
    ;Anführungszeichen entfernen falls vorhanden
    $Value = StringReplace($Value,'"',"")
    ;Defaulteintrag erkennen und setzen
    If $Value = "@" Then $Value = "(Default)"

    ;Typ und Daten ermitteln
    If StringInStr($LineRead, "hex:") Then
    $Type = "REG_BINARY"
    ;Prüfen ob Wert erstellt/Geändert oder entfernt werden soll
    If StringRight($LineRead,1) = "-" Then
    $Action = "DEL"
    Else
    $Action = "ADD"
    $Data = StringRight($LineRead, StringLen($LineRead) - StringInStr($LineRead,"hex:") - 3)
    $Data = _ParseRegData($OpenReg, $Data, $Type)
    ;$Data = StringReplace($Data, "," ,"")
    EndIf
    ElseIf StringInStr($LineRead, "dword:") Then
    $Type = "REG_DWORD"
    ;Prüfen ob Wert erstellt/Geändert oder entfernt werden soll
    If StringRight($LineRead,1) = "-" Then
    $Action = "DEL"
    Else
    $Action = "ADD"
    $Data = StringRight($LineRead, StringLen($LineRead) - StringInStr($LineRead,"dword:") - 5)
    $Data = "0x" & $Data
    EndIf
    ElseIf StringInStr($LineRead, "hex(7):") Then
    $Type = "REG_MULTI_SZ"
    ;Prüfen ob Wert erstellt/Geändert oder entfernt werden soll
    If StringRight($LineRead,1) = "-" Then
    $Action = "DEL"
    Else
    $Action = "ADD"
    $Data = StringRight($LineRead, StringLen($LineRead) - StringInStr($LineRead,"hex(7):") - 6)
    $Data = _ParseRegData($OpenReg, $Data, $Type)
    EndIf
    ElseIf StringInStr($LineRead, "hex(2):") Then
    $Type = "REG_EXPAND_SZ"
    ;Prüfen ob Wert erstellt/Geändert oder entfernt werden soll
    If StringRight($LineRead,1) = "-" Then
    $Action = "DEL"
    Else
    $Action = "ADD"
    $Data = StringRight($LineRead, StringLen($LineRead) - StringInStr($LineRead,"hex(2):") - 6)
    $Data = _ParseRegData($OpenReg, $Data, $Type)
    EndIf
    Else
    $Type = "REG_SZ"
    ;Prüfen ob Wert erstellt/Geändert oder entfernt werden soll
    If StringRight($LineRead,1) = "-" Then
    $Action = "DEL"
    Else
    $Action = "ADD"
    $Data = StringRight($LineRead, StringLen($LineRead) - StringInStr($LineRead,"="))
    ;Prüfen ob der String Mehrzeilig ist
    While 1
    If StringRight($Data,1) <> '"' Then
    $Data = $Data & @CRLF & FileReadLine($OpenReg)
    Else
    ExitLoop
    EndIf
    WEnd
    ;Escapezeichen bei Pfadangaben entfernen
    $Data = StringReplace($Data,"\\","\")
    ;Anführungszeichen entfernen
    $Data = StringMid($Data, 2,StringLen($Data)-2)
    EndIf
    EndIf

    ;MsgBox(0, "debug", "Aktion: " & $Action & @CRLF & "Typ: " & $Type & @CRLF & "Wert: " & $Value & @CRLF & "Daten: " & $Data)
    EndIf

    ;Array füllen
    ;ReDim $retArr[$Counter+1][6]
    $retArr[0][0] = $Counter
    If $Counter <> 0 And $Action <> "" Then
    $retArr[$Counter][0] = $Action
    $retArr[$Counter][1] = $MainKey
    $retArr[$Counter][2] = $SubKey
    $retArr[$Counter][3] = $Type
    $retArr[$Counter][4] = $Value
    $retArr[$Counter][5] = $Data
    EndIf
    WEnd
    ;Reg Datei schließen
    FileClose($OpenReg)
    ;Arraygröße anpassen (verkleinern)
    ReDim $retArr[$Counter+1][6]
    Return $retArr
    EndFunc

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

    Func _ParseRegData($File, $Line, $Type)
    Local $tmpArr, $retStr, $i

    ;Zeilenumbrüche zusammenfügen
    While 1
    If StringRight($Line,1) = "\" Then
    ;Backslash entfernen
    $Line = StringReplace($Line, "\", "")
    ;Zeilen zusammenfügen
    $Line = $Line & FileReadLine($File)
    Else
    ExitLoop
    EndIf
    WEnd

    ;Backslash entfernen
    $Line = StringReplace($Line, "\", "")
    ;Leerzeichen entfernen
    $Line = StringStripWS($Line,8)

    If $Type = "REG_BINARY" Then
    $retStr = StringReplace($Line, ",", "")
    Else
    ;Steuerzeichen(?) entfernen
    $Line = StringReplace($Line, "00,", "")

    ;Aufspliten der einzelnen String-Bytes
    $tmpArr = StringSplit($Line, ",")

    ;Ascii-Codes zurückrechnen und String daraus erstellen
    For $i = 1 to UBound($tmpArr) - 1
    $retStr = $retStr & Chr(Dec($tmpArr[$i]))
    Next
    EndIf
    Return $retStr
    EndFunc

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

    ;Importiert von File.au3
    Func _IMPFileCountLines($sFilePath)
    ;~ Local $N = FileGetSize($sFilePath) - 1
    ;~ If @error Or $N = -1 Then Return 0
    ;~ Return StringLen(StringAddCR(FileRead($sFilePath, $N))) - $N + 1
    Local $hFile, $sFileContent, $aTmp
    $hFile = FileOpen($sFilePath, 0)
    If $hFile = -1 Then Return SetError(1, 0, 0)
    $sFileContent = StringStripWS(FileRead($hFile), 2)
    FileClose($hFile)
    If StringInStr($sFileContent, @LF) Then
    $aTmp = StringSplit(StringStripCR($sFileContent), @LF)
    ElseIf StringInStr($sFileContent, @CR) Then
    $aTmp = StringSplit($sFileContent, @CR)
    Else
    If StringLen($sFileContent) Then
    Return 1
    Else
    Return SetError(2, 0, 0)
    EndIf
    EndIf
    Return $aTmp[0]
    EndFunc ;==>_FileCountLines

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

    ;TestCode
    #cs
    #include <array.au3>
    Dim $testArr
    $Reg = FileOpenDialog("Choose a registry file", @ScriptDir, "Registry Files (*.reg)", 1)
    $testArr = _RegParse($Reg)
    _ArrayDisplay($testArr)
    #ce

    [/autoit]

    Edit: Bug mit doppeltem "\" in Pfadangaben korrigiert
    Edit 2: Geschwindigkeit verbessert (Redim in der Schleife ersetzt)

    2 Mal editiert, zuletzt von Bitboy (29. Juli 2009 um 17:50)