Aktionen

ZnilTools:JP ProfileAnalyzer

Aus znilwiki

Die druckbare Version wird nicht mehr unterstützt und kann Darstellungsfehler aufweisen. Bitte aktualisiere deine Browser-Lesezeichen und verwende stattdessen die Standard-Druckfunktion des Browsers.

Changelog:

  • 19.11.2018: erste Version 1.0.0.17
  • 19.11.2018: Version 1.0.0.25: In den Statistiken wird nun auch die Anzahl der Schlüssel angezeigt, Neuer Parameter --noprogress und bessere Parameter-Verarbeitung



Download

Der Quellcode ist im Download mit enthalten!



Vorwort

Ich wollte ein paar JPUser.dat auf deren Inhalt hin analysieren. In der Regel interessiert mich welchen Anteil welche Software an der Registry hat.
Dazu habe ich das hier beschriebene Tool geschrieben.


Anleitung

Einfach das Programm zusammen mit einer JPUser.dat starten:

JP_ProfileAnalyzer.exe JPUser.dat

Folgende Parameter sind noch möglich:

--depth=    : Bis zu welcher Tiefe sollen die Schlüssel zusammengefasst werden, Default Wert ist --depth=3
--show=     : Ab welchen Prozentwert sollen die Werte angezeigt werden, Default Wert ist --show=10, Minimalwert ist 1



Beispiele

ClipCapIt-181119-171429.PNG


ClipCapIt-181119-171541.PNG


Wenn man mit der --depth= ein wenig spielt bekommt man dann auch den Verursacher eines Riesen-Profiles heraus:

ClipCapIt-181119-162628.PNG

In diesem Fall hat sicher der "PhotoPrintingWizard" sämtliche Drucker in allen jemals vorhandenen Sitzung für jeden Server gemerkt,


Tipps und Merkwürdiges Verhalten

Hier Analysiere ich ein Profil mit der Standardtiefe --depth=3:

ClipCapIt-181119-163929.PNG

Wenn ich die Tiefe jedoch um einen erhöhe verschwindet der Eintrag wieder (--depth=4):

ClipCapIt-181119-164043.PNG

Das ist erst einmal merkwürdig - aber trotzdem logisch:
Die verwendeten Begriff sind wie folgt:

Schlüssel: HKEY_CURRENT_USER\Software\Quadram\Ergo8\
Wert:      Test REG_SZ Ich bin ein Wert
  • Er addiert alle Werte unterhalb eines Registry-Schlüssels sofern diese der entsprechenden Tiefe entsprechen. Bei der Tiefe von 3 ist die Ebene Ergo8' halt die 3. Ebene (HKCU zählt nicht mit)
  • Bei der Anzahl werden nur die Werte addiert. Bei dem Volumen zählt er aber auch die Schlüssel / den Textstring dieser selbst mit, in diesem Fall die ganzen Unterschlüssel. Bei einem Programm mit vielen Schlüsseln kommt da einiges zusammen.
  • Erhöhe ich nun die Tiefe auf 4 wird der Schlüssel nicht mehr angezeigt - weil jede der Nachfolgenden Ebenen unter dem Schwellwert von --show=10 bleibt. Das ist nämlich z.B. ein Programm mit über 8.700 Unterschlüsseln die jeweils nur 8 Werte enthalten.



Quellcode

Wie so oft mit AutoIt geschrieben:

#NoTrayIcon
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=Icon256-32.ico
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_Description=Analyze JPUser.dat
#AutoIt3Wrapper_Res_Fileversion=1.0.0.26
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_Language=1031
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <array.au3>
#Include <string.au3>

Dim $sFilename				; Dateiname inklusive Pfad zur JPUser.dat
Dim $sTempLine				; die eingelesenen Zeilen werden hier temporär gespeichert
Dim $hSourceFile			; Zeiger auf die JPUser.dat
Dim $iTimerstart			; Startzeit der Filterung
Dim $iTimerend				; Endzeit der Filterung
Dim $iLineCounter = 0		; Zeilenzählen - als Status geben wir alle 100 Zeilen einen Punkt aus

Dim $i_MaxDepth = 3		; Maximale Schlüsseltiefe / Suchtiefe beim Addieren der Werte, aller darunter wird im Übergeordneten Schlüssel mit gespeichert
Dim $i_CurrentDepth = 0
Dim $s_temp = ""
Dim $s_LastKey = ""
Dim $i_TotalValues = 0	; Anzahl aller Werte
Dim $i_TotalSize = 0	; Größe alle Werte in Summe
Dim $i_TotalKeys = 0	; Anzahl aller Schlüssel
Dim $a_JPUserDAT[1][7]	; [0][0] = Anzahl Schlüssel
						; [x][1] = Name des Schlüssels
						; [x][2] = Anzahl der Werte unter diesem Schlüssel
						; [x][3] = Größe der Werte unter diesem Schlüssel
						; [x][4] = Anteil Anzahl an Gesamt (Prozent)
						; [x][5] = Anteil Größe an Gesamt (Prozent)
						; [x][6] = Anzahl an Schlüsseln in diesem Schlüsselzweig
$a_JPUserDAT[0][0] = 0
$a_JPUserDAT[0][1] = "Name"
$a_JPUserDAT[0][2] = "Anzahl Werte"
$a_JPUserDAT[0][3] = "Volumen Werte"
$a_JPUserDAT[0][4] = "Anteil Anzahl"
$a_JPUserDAT[0][5] = "Anteil Größe"
$a_JPUserDAT[0][6] = "Anteil Prozent"
Dim $sBackupTempline = ""
Dim $i_ShowValuesOver = 10 ; Nur Werte über 10% anzeigen
Dim $b_NoProgress = False


;                             10        20        30        40        50        60        70        80
;                 	 12345678901234567890123456789012345678901234567890123456789012345678901234567890
Dim $sHelp = 		'+------------------------------------------------------------------------------' & @CRLF & _
					'| JP_ProfileAnalyzer.exe - Version ' & FileGetVersion(@ScriptName) & @CRLF & _
					'+------------------------------------------------------------------------------' & @CRLF & _
					'| 2011-2015 von Bernhard Linz für http://znil.net - Kontakt: Bernhard@znil.net' & @CRLF & _
					'+------------------------------------------------------------------------------' & @CRLF & _
					@CRLF & _
					'Analysiert den Inhalt einer JPUser.dat und listet die Schlüssel ' & @CRLF & _
					'in Prozent für Anzahl und Volumen im Verhältnis zur Gesamtdatei auf' & @CRLF & _
					'Damit kann man sich einen Überblick über die Belegung verschaffen.' & @CRLF & _
					'-------------------------------------------------------------------------------' & @CRLF & _
					@CRLF & _
					'Aufruf:' & @CRLF & _
					@ScriptName & ' [Pfad][Dateinname] <Parameter>' & @CRLF & _
					@CRLF & _
					'Beispiel:' & @CRLF & _
					@ScriptName & ' D:\Profiles\Benutzer\JumpingProfile\JPUser.dat' & @CRLF & _
					@CRLF & _
					'Parameter:' & @CRLF & _
					' --depth=     : Bis zu welcher Tiefe sollen die Schlüssel zusammengefasst werden' & @CRLF & _
					'                Default Wert ist --depth=3' & @CRLF & _
					@CRLF & _
					' --show=      : Ab welchen Prozentwert sollen die Werte angezeigt werden,' & @CRLF & _
					'                Default Wert ist --show=10, Minimalwert ist 1' & @CRLF & _
					@CRLF & _
					' --noprogress : Keine Fortschrittsanzeige mit Punkten anzeigen' & @CRLF & _
					@CRLF & _
					' Die Reihenfolger der Parameter und Optionen ist beliebig. Wird bei einem' & @CRLF & _
					' Parameter/Option kein - am Anfang gefunden so wird dieser ' & @CRLF & _
					' als Dateiname gesetzt.' & @CRLF & _
					'+------------------------------------------------------------------------------' & @CRLF & _
					'| JP_ProfileAnalyzer ist FREEWARE! Kopieren, weitergeben ausdrücklich erlaubt!' & @CRLF & _
					'| Die jeweils aktuelleste Version und Anleitungen findet Ihr unter:' & @CRLF & _
					'| https://znil.net/index.php?title=ZnilTools:JP_ProfileAnalyzer' & @CRLF & _
					'+------------------------------------------------------------------------------' & @CRLF



; ###################################################################################
; _ANSI2OEM löst das Problem mit dem Umlauten und anderen Sonderzeichen. Es wandelt Text so um das er korrekt in der DOS-Box dargestellt wird
; So können hier im Quellcode auch Umlaute verwendet werden (in den Textausgaben) und diese werden dann korrekt dargestellt
; Dank an Xenobiologist von AutoIt.de für diese Lösung: http://www.autoit.de/index.php?page=Thread&threadID=9461&highlight=ANSI2OEM
Func _ANSI2OEM($text)
	$text = DllCall('user32.dll', 'Int', 'CharToOem', 'str', $text, 'str', '')
	Return $text[2]
EndFunc   ;==>_ANSI2OEM

Func _ByteSuffix($iBytes, $iRound = 2) ; By Spiff59
    Local $A, $aArray[9] = [" B", " KB", " MB", " GB", " TB", " PB", "EB", "ZB", "YB"]
    While $iBytes > 1023
        $A += 1
        $iBytes /= 1024
    WEnd
    Return Round($iBytes, $iRound) & $aArray[$A]
EndFunc   ;==>_ByteSuffix

Func _AddThousandDotNEU($iZahl)
	Return StringRegExpReplace(StringReverse(StringRegExpReplace(StringReverse($iZahl),"\d{3}","\0.")),"(?<![0-9])\.","",1)
EndFunc

; ###################################################################################
; Hauptprogramm
$iTimerstart = TimerInit()

; Prüfen  ob ein Parameter angegeben wurde - sonst beenden
If $CmdLine[0] = 0 Then
	ConsoleWrite(_ANSI2OEM("FEHLER - Keine Datei angegeben, /? für Hilfe" & @CRLF))
	Exit 0
EndIf

;Prüfen ob wir die Hilfe ausgeben sollen
If $CmdLine[1] = "/?" Then
	ConsoleWrite(_ANSI2OEM($sHelp))
	Exit 0
EndIf

For $i = 1 To (UBound($CmdLine) - 1) Step 1
	If StringLeft($CmdLine[$i], 8) = "--depth=" Then
		$i_MaxDepth = Int(StringMid($CmdLine[$i], 9))
		If $i_MaxDepth = 0 Then
			$i_MaxDepth = 3
		EndIf
	ElseIf StringLeft($CmdLine[$i], 7) = "--show=" Then
		$i_ShowValuesOver = Int(StringMid($CmdLine[$i], 8))
		If $i_ShowValuesOver = 0 Then
			$i_ShowValuesOver = 10
		EndIf
	ElseIf $CmdLine[$i] = "--noprogress" Then
		$b_NoProgress = True
	ElseIf StringLeft($CmdLine[$i],1) = "-" Then
		ConsoleWrite(_ANSI2OEM("Unbekannter Parameter: " & $CmdLine[$i] & @CRLF))
		Exit 1
	Else
		$sFilename = $CmdLine[$i]
	EndIf
Next



; Holen wir uns den Dateinamen - oder was auch immer da steht
;~ $sFilename = $CmdLine[1]
ConsoleWrite("STATUS - Verarbeite Datei " & $sFilename)
ConsoleWrite(@CRLF & "=> JP_ProfileAnalyzer = 2018 znil.net <=" & @CRLF)

; Analyze!
ConsoleWrite("STATUS - Analysiere Datei ")
$hSourceFile = FileOpen($sFilename,0)
If $hSourceFile = -1 Then
	ConsoleWrite(_ANSI2OEM(@CRLF & "FEHLER - Konnte " & $sFilename & "nicht öffnen" & @CRLF))
	Exit 1
EndIf
;~ $hTargetFile = FileOpen($sFilename & ".temp.txt",34)


While 1
	$sTempLine  = FileReadLine($hSourceFile)
	If @error <> -1 Then               ;123456789012345678
		$sBackupTempline = $sTempLine ; Wert einmal sichern, inklusive der Umgebung hinten dran
		If StringLeft($sTempLine,18) = "HKEY_CURRENT_USER\" Then
			$i_TotalKeys = $i_TotalKeys + 1
			; Schritt 0: Umgebung hinten abschneiden
			$sTempLine = StringReverse($sTempLine)
			$sTempLine = StringMid($sTempLine, StringInStr($sTempLine, "[") + 2)
			$sTempLine = StringReverse($sTempLine)

			; Schritt 1: Die Tiefe des Schlüssel ermitteln. Das machen wir indem wir die Anzahl der \ Zählen. Nicht 100% Perfekt aber ausreichend.
			$s_temp = StringReplace($sTempLine, "\", "|")
			$i_CurrentDepth = @extended
			$i_CurrentDepth = $i_CurrentDepth - 1

			; Schritt 2: Wenn die Tiefe die maximale Tiefe überschreitet schneiden wir den Rest ab.
			If $i_CurrentDepth > $i_MaxDepth Then
				$sTempLine = StringLeft($sTempLine, StringInStr($sTempLine, "\", 0, ($i_MaxDepth + 1)))
			EndIf

			; Schritt 3: Nun prüfen wir ob wir mit dem vorherigen Schlüssel übereinstimmen. Falls Nein legen wir im Array einen neuen Zähler an.
			If $sTempLine <> $s_LastKey Then
				$s_LastKey = $sTempLine
				; Stimmt nicht überein, wir legen einen neuen Zähler im Array an
				$a_JPUserDAT[0][0] = $a_JPUserDAT[0][0] + 1
				Redim $a_JPUserDAT[ $a_JPUserDAT[0][0] + 1 ][7]
				; Neuen Zähler mit Werten füllen
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][1] = $sTempLine
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][2] = 0
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][3] = (StringLen($sBackupTempline) * 2 ) ; Unicode! 2 Byte pro Zeichen!
				$i_TotalSize = $i_TotalSize + (StringLen($sBackupTempline) * 2 )
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][4] = 0
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][5] = 0
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][6] = 1
			Else
				; Der (ggf. gekürzte) Keyname stimmt mit dem vorherigen Keynamen überein
				; Wir müssen nichts tun! Die nachfolgenden Werte sollen einfach in der verherigen mit einfließen.
				; Den Schlüssel selbst rechnen wir aber zu der Menge hinzu, Kleinvieh macht auch Mist!
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][3] = $a_JPUserDAT[ $a_JPUserDAT[0][0] ][3] + (StringLen($sBackupTempline) * 2 ) ; Unicode! 2 Byte pro Zeichen!
				$i_TotalSize = $i_TotalSize + (StringLen($sBackupTempline) * 2 )
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][6] = $a_JPUserDAT[ $a_JPUserDAT[0][0] ][6] + 1
			EndIf
		Else
			; Kein neuer Schlüssel, ergo muss es ein Wert sein.
			; Aber bitte nur wenn wir schon mindestens einen Zähler haben!
			If $a_JPUserDAT[0][0] > 0 Then
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][2] = $a_JPUserDAT[ $a_JPUserDAT[0][0] ][2] + 1
				$i_TotalValues = $i_TotalValues + 1
				$a_JPUserDAT[ $a_JPUserDAT[0][0] ][3] = $a_JPUserDAT[ $a_JPUserDAT[0][0] ][3] + (StringLen($sTempLine) * 2)
				$i_TotalSize = $i_TotalSize + (StringLen($sBackupTempline) * 2 )
			EndIf
		EndIf
		; Nachster Abschnitt ist nur Fortschrittsanzeige
		If $b_NoProgress = False Then
			$iLineCounter = $iLineCounter + 1
			If $iLineCounter > 99 Then
				ConsoleWrite(".")
				$iLineCounter = 0
			EndIf
		EndIf
	Else
		; Dateiende erreicht, raus aus der Schleife!
		ExitLoop
	EndIf
WEnd

FileClose($hSourceFile)


; Zusammenfassung!
ConsoleWrite(" fertig! Berechne Statistiken." & @CRLF & @CRLF)
; [x][1] = Name des Schlüssels
; [x][2] = Anzahl der Werte unter diesem Schlüssel
; [x][3] = Größe der Werte unter diesem Schlüssel
; [x][4] = Anteil Anzahl an Gesamt (Prozent)
; [x][5] = Anteil Größe an Gesamt (Prozent)
; [x][6] = Anzahl an Schlüsseln in diesem Schlüsselzweig

For $i = 1 To $a_JPUserDAT[0][0]
	$a_JPUserDAT[$i][4] = Round($a_JPUserDAT[$i][2] / $i_TotalValues * 100, 2)
	$a_JPUserDAT[$i][5] = Round($a_JPUserDAT[$i][3] / $i_TotalSize * 100, 2)
	If $a_JPUserDAT[$i][4] > $i_ShowValuesOver Or $a_JPUserDAT[$i][5] > $i_ShowValuesOver Then
		ConsoleWrite(_ANSI2OEM($a_JPUserDAT[$i][1] & @CRLF))
		ConsoleWrite(_ANSI2OEM("Anzahl Schlüssel .......: " & _AddThousandDotNEU($a_JPUserDAT[$i][6]) & @CRLF))
		ConsoleWrite("Anzahl Werte ...........: " & _AddThousandDotNEU($a_JPUserDAT[$i][2]) & @CRLF)
		ConsoleWrite("Volumen ................: " & _ByteSuffix($a_JPUserDAT[$i][3]) & @CRLF)
		ConsoleWrite("Anteil Anzahl an Gesamt : " & $a_JPUserDAT[$i][4] & "%" & @CRLF)
		ConsoleWrite("Anteil Volumen an Gesamt: " & $a_JPUserDAT[$i][5] & "%" & @CRLF & @CRLF)
	EndIf
Next

ConsoleWrite(_ANSI2OEM("Schlüssel Gesamt : " & _AddThousandDotNEU($i_TotalKeys) & @CRLF))
ConsoleWrite("Werte Gesamt ....: " & _AddThousandDotNEU($i_TotalValues) & @CRLF)
ConsoleWrite("Volumen Gesamt ..: " & _ByteSuffix($i_TotalSize) & @CRLF)
ConsoleWrite(@CRLF)

ConsoleWrite(_ANSI2OEM("Es wurden nur Werte über " & $i_ShowValuesOver & "% angezeigt" & @CRLF))
ConsoleWrite(@CRLF)

$iTimerend = TimerDiff($iTimerstart) / 1000
ConsoleWrite("Fertig, Laufzeit " & StringRegExpReplace($iTimerend,"(\d*)\.(\d{2})(\d*)","$1,$2") & " sec" & @CRLF & @CRLF)
Exit 0



Kommentare

Loading comments...