JumpingProfiles:JPProfileRefresh
Aus znilwiki
Ein Kunde löscht bei Problemen von Mitarbeitern immer die JPUser.dat
.
Da wir über die GroupLogin.dat
und GroupInit.dat
Vorseinstellungen für die Programme verteilen merken die Benutzer davon auch nicht viel, alles startet wie gewohnt.
Nun gabe es aber leider 2 Benutzergruppen die häufiger Probleme hatten - und der Admin dort dementsprechend häufiger deren JPUser.dat
gelöscht hat.
Leider konnte ich den Admin nicht davon überzeugen mal eine Ursachenforschung zu betreiben - früher kam es 10 mal im Monat vor, seit JP nur noch 1 mal, da war er schon glücklich.
Diese beiden Benutzergruppen nutzen leider Programme die unmengen an Einstellungen in der Registry machen - Ansichten, welche Spalten in Tabellen angezeigt werden sollen und so weiter.
Da darin viel Arbeit steckt hat der Admin bisher immer die Registry-Schlüssel dieser Anwendung per Hand aus der JPUser.dat
kopiert und im Anschluss wieder zurück in die neue JPUser.dat
kopiert.
Er bat mich das ganze mal zu vereinfachen - und deshalb gibt es nun die JP_ProfilRefresher.exe
Beschreibung
- Commandline Programm welchen man eine
JPUser.dat
übergibt - Die
JPUser.dat
wird geleert, es bleiben also nur noch der Header der Datei übrig - Das Programm liest alle Textdateien auf das Muster JP_ProfilRefresher*.txt passen ein (man beachte den * !)
- Alle in diesen Textdateien aufgeführten Schlüssel werden wieder in die
JPUser.dat
zurück geschrieben - Eine Kopie der Original
JPUser.dat
wird alsJPUser.dat.OLD
im gleichen Verzeichnis abgelegt
Download
Download: JP_ProfileRefresher.zip
Aufruf
- Kopiert die
JP_ProfilRefresher.exe
und dieJP_ProfilRefresher.txt
an eine Ort euer wahl - bearbeitet die
JP_ProfilRefresh.txt
und fügt dort die Registry-Schlüssel ein die erhalten bleiben sollen, z.B.
HKEY_CURRENT_USER\Software\VB and VBA Program Settings\INPLAST\
- Ein Schlüssel pro Zeile!
- Es wird ein "Text in Text" Vergleich gemacht. Ihr könntet also auch nur
\VB and VBA Program Settings\
- angeben - Nutzung auf eigene Gefahr!
- Es werden nur Schlüssel beachtet - keine Werte! Also nur die "Ordner", nicht die "Dateien"!
- Öffnet eine Eingabeaufforderung
- Aufruf ist
JP_ProfilRefresher.exe JPUser.dat JP_ProfilRefresher.exe \\server\freigabe\testbenutzer\JumpingProfile\JPUser.dat JP_ProfilRefresher.exe D:\Profile\testbenutzer\JumpingProfile\JPUser.dat
- Alternativ könnt Ihr auch eine
JPUser.dat
per Drag&Drop auf dieJP_ProfilRefresher.exe
ziehen.<r>
Bequemer Einsatz in der Praxis
In der Praxis betraf es nur einige wenige Benutzer welche diese Sonderbehandlung brauchten ... wie mache es jetzt für den Admin möglichst einfach?
- Erstellt eine Freigabe / Ordner in welcher Ihr folgende Dateien ableget
- Die
JP_ProfilRefresher.exe
- Eine
JP_ProfilRefresher-Anwendungsname.txt
für jede Anwendung die eine solche Sonderbehandlung haben soll
- Die
Beispiel:
\\server\freigabe\JP$\JP_ProfileRefresh\ |- JP_ProfileRefresher.exe |- JP_ProfileRefresher-INPLAST.txt +- JP_ProfileRefresher-XAP.txt
Die beiden JP_ProfileRefresher-*.txt
> enthalten die jeweiligen Registry-Schlüssel die erhalten bleiben sollen.
In JumpingProfiles haben nun 2 JP-Gruppen:
JP_INPLAST JP_XAP
beide Gruppen bekommen nun eine FileOperation.dat
mit folgendem Inhalt (Pfade und Dateiname anpassen!):
============================================================
; File: FileOperation.dat
;============================================================
;
; Comment: File system operation
;
; Format: [<Profile version>:<Environment>]
; #<Element>
; Operation = COPY | CREATE | DELETE
; Event = FIRST | LOGIN | LOGOUT | LAST
; EventScope = GLOBAL | MACHINE | ENVIRONMENT | VERSION
; Replace = NEVER | ALWAYS | LATEST | DATE
; Date = <Date> (YYYY-MM-DD {HH:MM:SS})
; Recursion = ON | OFF
; Source = <Source>
; Destination = <Destination>
; Filter = <Filter>
;
;============================================================
[Header]
JP version = 4.6.0.0
JPManagerCore version = 4.6.0.0
JPManager module version = 4.6.0.0
[DEFAULT]
#Copy JP_ProfileRefresh.exe for Inplast
Operation = COPY
Event = LOGIN
Replace = LATEST
Source = \\server\JP$\JP_ProfileRefresh\JP_ProfileRefresher.exe
Destination = \\server\Profiles$\%USERNAME%\JumpingProfile\
#Copy JP_ProfileRefresh.txt for Inplast
Operation = COPY
Event = LOGIN
Replace = LATEST
Source = \\server\JP$\JP_ProfileRefresh\JP_ProfileRefresher-INPLAST.txt
Destination = \\server\Profiles$\%USERNAME%\JumpingProfile\
Die FileOperation.dat
könnt Ihr natürlich auch einfach im JP-Manager erstellen:
-
Was wird nun passieren?
Wenn sich Benutzer dieser beiden Gruppen anmelden wird diesen die JP_ProfileRefresher.exe
sowie die notwendigen Textdateien mit den Schlüsseln in ihr persönliches JumpingProfile Verzeichnis kopiert - also dorthin wo auch schon die JPUser.dat
liegt.
Nach eine Anmeldung sieht es in dem Verzeichnis also z.B. so aus:
Wenn der Admin nun die JPUser.dat
löschen will, sieht er die vorhandene JP_ProfileRefresher.exe
.
Und dann zieht er die Datei JPUser.dat
einfach per Drag&Drop auf die JP_ProfileRefresher.exe
-> Fertig!
Ergebnis:
Das ganze kann man auch hier einbauen: JPProfileReset - Benutzer kann selbst sein Profil zurück setzen
Das Skript was wir dort verwenden hat den eventuellen Aufruf der JP_ProfileRefresher.exe
bereits eingbaut.
Da eine Sicherheitskopie mit der Endung .OLD angelegt wird kann JPProfileReset sogar den Ursprungszustand wieder herstellen.
Quellcode JP_ProfileRefresher
Wieder einmal in AutoIt geschrieben:
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Icon=Icon256-32.ico
#AutoIt3Wrapper_UseUpx=n
#AutoIt3Wrapper_Change2CUI=y
#AutoIt3Wrapper_Res_Description=Oktober 2014 Bernhard Linz
#AutoIt3Wrapper_Res_Fileversion=1.0.2.25
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_Language=1031
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <array.au3>
#Include <string.au3>
Opt('MustDeclareVars', 1)
Dim $sFilename ; Dateiname inklusive Pfad zur JPUser.dat
Dim $aJPProfileRefresherLines[1] ; Hier stehen die Zeilen aus den JP_ProfileRefresher*.txt drin
Dim $hJPProfileRefresherTXT ; Zeiger auf die JP_ProfileRefresher*.txt
Dim $hJPProfileRefresherTXTSearch ; Suchzeiger auf alle JP_ProfileRefresher*.txt Dateien im aktuellen Verzeichnis
Dim $sJPProfileRefresherFile ; Konkrete Dateinamen der gefundenen JP_ProfileRefresher*.txt Dateien
Dim $sTempLine ; die eingelesenen Zeilen werden hier temporär gespeichert
Dim $bReadTheLines = False ; Boolean - wird zum Leerzeilen überspringen genutzt
Dim $hSourceFile ; Zeiger auf die JPUser.dat
Dim $hTargetFile ; Zeiger auf die neue Version der JPUser.dat
Dim $bWriteToTarget ; Boolean - wenn False werden die eingelesenden Zeilen nicht geschrieben
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
; 10 20 30 40 50 60 70 80
; 12345678901234567890123456789012345678901234567890123456789012345678901234567890
Dim $sHelp = '+------------------------------------------------------------------------------' & @CRLF & _
'| JP_ProfileRefresher.exe - Version ' & FileGetVersion(@ScriptName) & @CRLF & _
'+------------------------------------------------------------------------------' & @CRLF & _
'| 2014 von Bernhard Linz für http://znil.net - Kontakt: Bernhard@znil.net' & @CRLF & _
'+------------------------------------------------------------------------------' & @CRLF & _
@CRLF & _
'Vorgeschichte:' & @CRLF & _
'--------------' & @CRLF & _
'Dient dazu eine JPUser.dat in einen "Fast wie gelöscht" Zustand zu bringen' & @CRLF & _
'Hntergund ist das die 99% Universallösung bei Problemen das Löschen oder' & @CRLF & _
'Umbenennen der JPUser.dat ist - wenn der Benutzer sich etwas verkonfiguriert' & @CRLF & _
'hat oder ähnliches (Die Admins löschen eigentlich viel zu schnell, aber macht' & @CRLF & _
'die Sache schön einfach).' & @CRLF & _
'Schlecht ist wenn eine Anwendung mehrere hundert bis tausend Schlüssel für die' & @CRLF & _
'vom Benutzer gemachten Einstellungen speichert wie Sortierfolge, Spaltenbreiten' & @CRLF & _
'oder auch Ansichten etc. - diese muss er dann nämlich alle wieder neu machen' & @CRLF & _
'sofern die Einstellungen nicht einfach per GroupInit.dat vorgegeben werden' & @CRLF & _
'können (was die bessere Lösung wäre aber beim Kunden nicht in Frage kam' & @CRLF & _
'-------------------------------------------------------------------------------' & @CRLF & _
@CRLF & _
'Funktionsweise:' & @CRLF & _
'---------------' & @CRLF & _
'Statt die ganze JPUser.dat einfach zu löschen, filtern wir nur alle Schlüssel' & @CRLF & _
'aus - bis auf diejenigen die erhalten bleiben sollen - Ähnlich der Funktion der' & @CRLF & _
'FadeOut.dat, nur umgekehrt - wir geben an welche Schlüssel noch übrig bleiben' & @CRLF & _
'statt der Schlüssel die gelöscht werden sollen. Quelle ist eine'& @CRLF & _
' JP_ProfileRefresher.txt' & @CRLF & _
'im gleichen Verzeichnis wie dieses Script. In dieser Textdatei steht pro Zeile' & @CRLF & _
'ein Registry-Schlüssel der erhalten werden soll. (Schlüssel, nicht Werte =' & @CRLF & _
'"Verzeichnisse, nicht Dateien!")' & @CRLF & _
'Alternativ sind auch mehrere Quellen möglich, deren Name muss aber jeweils mit' & @CRLF & _
'"JP_ProfileRefresher" beginnen und mit ".txt" enden, z.B.' & @CRLF & _
'JP_ProfileRefresher-XAP.txt und JP_ProfileRefresher-INPLAST.txt -> beide Dateien' & @CRLF & _
'werden eingelesen und berücktsichtigt! Die Anzahl ist nicht begrenzt.' & @CRLF & _
'-------------------------------------------------------------------------------' & @CRLF & _
@CRLF & _
'Aufruf:' & @CRLF & _
'-------' & @CRLF & _
@ScriptName & ' [Pfad][Dateinname]' & @CRLF & _
@CRLF & _
'Beispiel:' & @CRLF & _
@ScriptName & ' D:\Profiles\Benutzer\JumpingProfile\JPUser.dat' & @CRLF & _
@CRLF & _
'Beispiel für eine Batchverarbeitung: (Forfiles ist in jedem Windows enthalten)' & @CRLF & _
@CRLF & _
'Forfiles /P "D:\PF" /S /M JPUser.dat /C "cmd /c D:\JP_ProfileRefresher.exe @path"' & @CRLF & _
@CRLF & _
' "D:\PF" steht für den Pfad zu den Benutzerprofilen, Forfiles kann nicht mit' & @CRLF & _
' UNC Pfaden umgehen (ggf. als Netzlaufwerk mounten)' & @CRLF & _
@CRLF & _
' Das Beispiel verarbeitet alle JPUser.dat in allen Verzeichnissen' & @CRLF & _
' unterhalb von "D:\PF"' & @CRLF & _
@CRLF & _
'+------------------------------------------------------------------------------' & @CRLF & _
'| JP_ProfileRefresher.exe ist FREEWARE! Kopieren, weitergeben ausdrücklich erlaubt!' & @CRLF & _
'| Die jeweils aktuelleste Version und Anleitungen findet Ihr unter:' & @CRLF & _
'| http://znil.net/index.php?title=ZnilTools:JP_ProfileRefresher.exe' & @CRLF & _
'+------------------------------------------------------------------------------' & @CRLF
; 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
; Holen wir uns den Dateinamen - oder was auch immer da steht
$sFilename = $CmdLine[1]
ConsoleWrite("STATUS - Verarbeite Datei " & $sFilename)
ConsoleWrite(@CRLF & "=> JP_ProfileRefresher => 2014 znil.net <=" & @CRLF)
; Holen wir uns die Schlüssel die ausgefiltert werden sollen
ConsoleWrite("STATUS - Lese JP_ProfileRefresher.txt Dateien ein .....")
;$hJPProfileRefresherTXTSearch = FileFindFirstFile(@ScriptDir & "\JP_ProfileRefresher*.txt")
;while 1
; $hJPProfileRefresherTXT = FileFindNextFile($hJPProfileRefresherTXTSearch)
; If @error Then ExitLoop
; MsgBox(0,"",$hJPProfileRefresherTXT)
;WEnd
;Exit
$aJPProfileRefresherLines[0] = 0
$hJPProfileRefresherTXTSearch = FileFindFirstFile(@ScriptDir & "\JP_ProfileRefresher*.txt")
While 1
$sJPProfileRefresherFile = FileFindNextFile($hJPProfileRefresherTXTSearch)
If @error Then ExitLoop
ConsoleWrite(_ANSI2OEM("Lese Datei ein: " & $sJPProfileRefresherFile) & @CRLF)
$hJPProfileRefresherTXT = FileOpen(@ScriptDir & "\" & $sJPProfileRefresherFile,0)
If $hJPProfileRefresherTXT = -1 Then
ConsoleWrite(_ANSI2OEM("FEHLER - Konnte " & $sJPProfileRefresherFile & " nicht öffnen") & @CRLF)
Exit 1
EndIf
While 1
$sTempLine = FileReadLine($hJPProfileRefresherTXT)
If @error <> -1 Then
If $sTempLine <> "" Then
$aJPProfileRefresherLines[0] = $aJPProfileRefresherLines[0] + 1
_ArrayAdd($aJPProfileRefresherLines,$sTempLine)
EndIf
Else
ExitLoop
EndIf
WEnd
FileClose($hJPProfileRefresherTXT)
ConsoleWrite(_ANSI2OEM("fertig (Es snd nun " & $aJPProfileRefresherLines[0] & " Einträge insgesamt)" & @CRLF))
WEnd
; Filtern!
ConsoleWrite("STATUS - Filtere Datei ")
$iTimerstart = TimerInit()
$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",2)
$bWriteToTarget = True
While 1
$sTempLine = FileReadLine($hSourceFile)
If @error <> -1 Then ;123456789012345678
If StringLeft($sTempLine,18) = "HKEY_CURRENT_USER\" Then
$bWriteToTarget = False
EndIf
If $bWriteToTarget = False Then
For $i = 1 To $aJPProfileRefresherLines[0]
If StringInStr($sTempLine,$aJPProfileRefresherLines[$i]) > 0 Then
$bWriteToTarget = True
EndIf
Next
EndIf
If $bWriteToTarget = True Then
FileWriteLine($hTargetFile,$sTempLine)
EndIf
$iLineCounter = $iLineCounter + 1
If $iLineCounter > 99 Then
ConsoleWrite(".")
$iLineCounter = 0
EndIf
Else
ExitLoop
EndIf
WEnd
FileClose($hSourceFile)
FileClose($hTargetFile)
$iTimerend = TimerDiff($iTimerstart) / 1000
ConsoleWrite(" fertig, Laufzeit " & StringRegExpReplace($iTimerend,"(\d*)\.(\d{2})(\d*)","$1,$2") & " sec" & @CRLF)
ConsoleWrite(_ANSI2OEM("Lösche eventuell vorhandene JPUser.dat.OLD") & @CRLF)
FileDelete($sFilename & ".OLD")
ConsoleWrite("Tausche JPUser.dat aus ....")
FileMove($sFilename, $sFilename & ".OLD",1)
FileMove($sFilename & ".temp.txt",$sFilename,1)
ConsoleWrite("fertig" & @CRLF & @CRLF)
Exit 0
; ###################################################################################
; _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