Skriptbasierter DomainJoin und Migration des lokalen Profils
Hallo Community, bisher war ich nur begeisterter Leser der Tips und Tricks. Nun brauche ich selbst das Wissen und die Erfahrung die sich hier im Forum wiederfindet
ich stehe gerade vor der Herausforderung, etwa 40zig NT 4 (!) Workstations in die Domäne aufzunehmen und dabei sicherzustellen, dass bereits installierte Software danach noch weiter tut.
einige Sachen habe ich schon als CMD-Skripte gebaut (Domainjoin, DNS Eintrag ändern mit reg.exe, DNS-Suffixsuchliste ändern).
Es befinden sich mehrere Benutzerprofile auf den Clients. Die Profile sollen nach dem Domänenbeitritt weiterhin lokal bleiben.
Da ich nicht jeden einzelnen Benutzer anmelden will, sollen alle Schritte, die bei einer ersten Anmeldung eines Benutzers mit seinem Domänenkonto am Rechner ausgeführt werden, per Skript ausgelöst werden.
Das blosse kopieren des BenutzerProfils von C:\Winnt\profiles\username nach C:\winnt\profiles\username.000 reicht dabei ja nicht aus um ordentlich zu funktionieren.
Zusätzlich muss ich die ntuser.dat sowie die userclass.dat laden und hierin die SIDs (localuser - domainuser) tauschen.
ich habe mir folgendes Vorgehen vorgestellt:
1. Profile auf C:\winnt\profiles auslesen und nur diejenigen in eine Datei (proflist.txt) schreiben die relevant sind. z.B. System gibt es in der AD nicht.
@echo off
set domain=000
cd /d C:\winnt\profiles
dir /B /A:D | findstr /r /v ^.*00.$>profile.txt
for /f "tokens=* delims=" %%i in (proflist.txt) do call :process %%i
goto :eof
:process
set profname=%1
if /I %profname%==system goto :cancel
if /I %profname%==other goto :cancel
xcopy %profroot%\%profname%\*.* %profroot%\%profname%.%domain%\*.* /S /C /H /E /R /K
goto :eof
:Cancel
@echo %profname%>>notmigrated.txt
goto :eof
2. die Datei profile.txt nochmals verwenden um neue einträge für jeden Domänenbenutzer unter HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\<USER> anzulegen. Dabei jeweils mittels psgetsid prüfen ob es für den Benutzeraccount bereits eine Entsprechung in der Domäne gibt.
@echo off
setlocal enableextensions
set adjoinUN=administrator
set adjoinPW=password
set dcname=DCNAME
set domainnb=ADSDOMAIN
set regspath="HKlm\software\microsoft\windows nt\currentversion\profilelist"
for /f "tokens=* delims=" %%i in ('reg.exe query %regspath%') do call :profimg %%i
goto :eof
:profimg
set foundsid=%1
set "usersid=%foundsid:[=%"
set "usersid=%usersid:]=%"
psgetsid -accepteula %usersid% >nul
set sidcheck=psgetsid.exe \\%dcname% -u %domainnb%\%adjoinUN% -p %adjoinPW% %usersid%
for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
echo %errorlevel%
)
goto :eof
:end
und hier komme ich nicht weiter: die Ausgabe des Errorlevels entspricht nicht dem was ich erwarte. Egal ob ein aus der profilelist.txt abgearbeiteter User in der Domäne ist (Errorlevel sollte 0 sein) oder nicht ise (Errorlevel NOT 0): Der Errorlevel ist immer gleich.?!
Im Anschluss wollte ich wie folgt weitermachen.
- wenn errorcode =1 dann sid/user auslassen und weitermachen
- wenn errorcode =0 dann mittels 'reg add' die DomänenSID unter HKlm\software\microsoft\windows nt\currentversion\profilelist eintragen.
- dann darunter den Reg_Expand_Sz Eintrag 'Profilimagepath' mit dem Wert: %SystemDrive%\Winnt\Profiles\<domainuser> eintragen.
- jeweiligen Domänenbenutzer auf HKlm\software\microsoft\windows nt\currentversion\profilelist\<SID von Domänenbenutzer> rekursiv berechtigen
Vielleicht könnt Ihr mir weiterhelfen.
Danke schon einmal
JPLC
ich stehe gerade vor der Herausforderung, etwa 40zig NT 4 (!) Workstations in die Domäne aufzunehmen und dabei sicherzustellen, dass bereits installierte Software danach noch weiter tut.
einige Sachen habe ich schon als CMD-Skripte gebaut (Domainjoin, DNS Eintrag ändern mit reg.exe, DNS-Suffixsuchliste ändern).
Es befinden sich mehrere Benutzerprofile auf den Clients. Die Profile sollen nach dem Domänenbeitritt weiterhin lokal bleiben.
Da ich nicht jeden einzelnen Benutzer anmelden will, sollen alle Schritte, die bei einer ersten Anmeldung eines Benutzers mit seinem Domänenkonto am Rechner ausgeführt werden, per Skript ausgelöst werden.
Das blosse kopieren des BenutzerProfils von C:\Winnt\profiles\username nach C:\winnt\profiles\username.000 reicht dabei ja nicht aus um ordentlich zu funktionieren.
Zusätzlich muss ich die ntuser.dat sowie die userclass.dat laden und hierin die SIDs (localuser - domainuser) tauschen.
ich habe mir folgendes Vorgehen vorgestellt:
1. Profile auf C:\winnt\profiles auslesen und nur diejenigen in eine Datei (proflist.txt) schreiben die relevant sind. z.B. System gibt es in der AD nicht.
@echo off
set domain=000
cd /d C:\winnt\profiles
dir /B /A:D | findstr /r /v ^.*00.$>profile.txt
for /f "tokens=* delims=" %%i in (proflist.txt) do call :process %%i
goto :eof
:process
set profname=%1
if /I %profname%==system goto :cancel
if /I %profname%==other goto :cancel
xcopy %profroot%\%profname%\*.* %profroot%\%profname%.%domain%\*.* /S /C /H /E /R /K
goto :eof
:Cancel
@echo %profname%>>notmigrated.txt
goto :eof
2. die Datei profile.txt nochmals verwenden um neue einträge für jeden Domänenbenutzer unter HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\<USER> anzulegen. Dabei jeweils mittels psgetsid prüfen ob es für den Benutzeraccount bereits eine Entsprechung in der Domäne gibt.
@echo off
setlocal enableextensions
set adjoinUN=administrator
set adjoinPW=password
set dcname=DCNAME
set domainnb=ADSDOMAIN
set regspath="HKlm\software\microsoft\windows nt\currentversion\profilelist"
for /f "tokens=* delims=" %%i in ('reg.exe query %regspath%') do call :profimg %%i
goto :eof
:profimg
set foundsid=%1
set "usersid=%foundsid:[=%"
set "usersid=%usersid:]=%"
psgetsid -accepteula %usersid% >nul
set sidcheck=psgetsid.exe \\%dcname% -u %domainnb%\%adjoinUN% -p %adjoinPW% %usersid%
for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
echo %errorlevel%
)
goto :eof
:end
und hier komme ich nicht weiter: die Ausgabe des Errorlevels entspricht nicht dem was ich erwarte. Egal ob ein aus der profilelist.txt abgearbeiteter User in der Domäne ist (Errorlevel sollte 0 sein) oder nicht ise (Errorlevel NOT 0): Der Errorlevel ist immer gleich.?!
Im Anschluss wollte ich wie folgt weitermachen.
- wenn errorcode =1 dann sid/user auslassen und weitermachen
- wenn errorcode =0 dann mittels 'reg add' die DomänenSID unter HKlm\software\microsoft\windows nt\currentversion\profilelist eintragen.
- dann darunter den Reg_Expand_Sz Eintrag 'Profilimagepath' mit dem Wert: %SystemDrive%\Winnt\Profiles\<domainuser> eintragen.
- jeweiligen Domänenbenutzer auf HKlm\software\microsoft\windows nt\currentversion\profilelist\<SID von Domänenbenutzer> rekursiv berechtigen
Vielleicht könnt Ihr mir weiterhelfen.
Danke schon einmal
JPLC
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 126772
Url: https://administrator.de/contentid/126772
Ausgedruckt am: 12.11.2024 um 22:11 Uhr
8 Kommentare
Neuester Kommentar
Hallo LuckyPuncher,
ändere doch mal:
in:
und nimm mal in
Die gehören da IMHO nicht nicht.?!
Den Rest machst du dann mit einer IF-Auswertung:
Gib mal Bescheid.
Gruß
Tsuki
ändere doch mal:
echo %errorlevel%
in:
echo Errorlevel :%sidcheck%
(''%sidcheck%')
die " und ' raus.Die gehören da IMHO nicht nicht.?!
Den Rest machst du dann mit einer IF-Auswertung:
If Errorlevel = 1 then goto Bedingung1
If Errorlevel = 0 then goto Bedingung0
Gib mal Bescheid.
Gruß
Tsuki
Hi LuckyPuncher,
dann könnte es eventuell dem Programm "PSGETSID.exe" liegen, dass es keine vernünftige Fehlerauswertung ausgibt.
Müßte man mal googeln oder nachfragen. Wenn der Entwickler von solchen Programmen die Fehlerauswertung nicht "so ernst" nimmt, dann kann man gleichen Effekt haben.
Gruß
Tsuki
dann könnte es eventuell dem Programm "PSGETSID.exe" liegen, dass es keine vernünftige Fehlerauswertung ausgibt.
Müßte man mal googeln oder nachfragen. Wenn der Entwickler von solchen Programmen die Fehlerauswertung nicht "so ernst" nimmt, dann kann man gleichen Effekt haben.
Gruß
Tsuki
Hallo LuckyPuncher,
warum eigentlich die ganzen Umwege über Variable und FOR-Schleife?
Sollte psgetsid einen Errorlevel zurückgeben (vovon ich eigentlich bei allen PS-Tools ausgehe), ist das relativ einfach über eine Zeile abzufangen
Grüße
rubberman
warum eigentlich die ganzen Umwege über Variable und FOR-Schleife?
Sollte psgetsid einen Errorlevel zurückgeben (vovon ich eigentlich bei allen PS-Tools ausgehe), ist das relativ einfach über eine Zeile abzufangen
psgetsid.exe \\%dcname% -u %domainnb%\%adjoinUN% -p %adjoinPW% %usersid% &&goto Erfolg ||goto Fehler
Grüße
rubberman
Moin LuckyPuncher,
die Abfrage des Errorlevels klappt bei dir nicht, weil für den CMD-Interpreter diese optisch auf Zeilen auseinadergezogene <u>Befehls<u>zeile
Ergo: Hast du VOR dem Ausführen der ersten FOR-Anweisung bzw des ersten PsGetSID ein ErrorLevel 0 drin, hast du es auch 200 Aufrufe lang.
War das Errorlevel vorher auf 77, dann wird dich eben diese 77 bis nach dem Klammer-Zu der DO-Anweisung begleiten.
Lies dir mal am CMD-Prompt [bei SetLocal /?] und/oder hier im Forum ein bisschen was an zum Thema "DelayedExpansion" und ändere (nachdem du es verstanden hast) die Mimik so ab:
[in deinem Batch:
Die FOR-Anweisung:
Biber
die Abfrage des Errorlevels klappt bei dir nicht, weil für den CMD-Interpreter diese optisch auf Zeilen auseinadergezogene <u>Befehls<u>zeile
...
for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
echo %errorlevel%
)
..
eben nur EINE Zeile ist, die der alle dort benötigten Variablen eben auch nur einmal (beim Loslaufen) aufgelöst werden.for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
echo %errorlevel%
)
..
Ergo: Hast du VOR dem Ausführen der ersten FOR-Anweisung bzw des ersten PsGetSID ein ErrorLevel 0 drin, hast du es auch 200 Aufrufe lang.
War das Errorlevel vorher auf 77, dann wird dich eben diese 77 bis nach dem Klammer-Zu der DO-Anweisung begleiten.
Lies dir mal am CMD-Prompt [bei SetLocal /?] und/oder hier im Forum ein bisschen was an zum Thema "DelayedExpansion" und ändere (nachdem du es verstanden hast) die Mimik so ab:
[in deinem Batch:
- Ganz am Anfang, wo sicherlich ein "echo off (o.ä.)" steht--->eine Zeile tiefer: "Setlocal EnableDelayedExpansion"
Die FOR-Anweisung:
...
for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
echo Aktuelles Errorlevel: !errorlevel!
IF !errorlevel! 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
)
..
-- ODER ohne verzögerte Variablenauflösung--for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
echo Aktuelles Errorlevel: !errorlevel!
IF !errorlevel! 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
)
..
...
for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
IF ErrorLevel 1 echo Aktuelles Errorlevel: 1 oder größer
IF ErrorLevel 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
)
..
Schönes Wochenendefor /f "tokens=* delims=" %%a in (''%sidcheck%') do (
IF ErrorLevel 1 echo Aktuelles Errorlevel: 1 oder größer
IF ErrorLevel 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
)
..
Biber
Uppps, sorry, LuckyPuncher,
mein Fehler.
Ich habe ein Gleichheitszeichen unterschlagen
Ich schrieb:
- entweder mit SetLocal EnableDelayedExpansion
was Bullshit ist, denn es muss lauten
... während die andere Syntax bei "ohne DelayedExpansion"/nur "Setlocal" richtig genannt wurde:
--> hier als "IF ERRORLEVEL 1 " ohne die doppelten Gleichheitszeichen und ohne %- oder !-Zeichen um die Variable Errorlevel (also NICHT %errorlevel% und auch nicht !errorlevel!
Tut mir leid, dass Du da ganz umsonst so eine Schleife geflogen bist.
Dafür hast du bei Gelegenheit einen Oneliner gut bei mir.
Zerknirscht
Biber
mein Fehler.
Ich habe ein Gleichheitszeichen unterschlagen
Ich schrieb:
- entweder mit SetLocal EnableDelayedExpansion
IF !errorlevel! 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
was Bullshit ist, denn es muss lauten
IF !errorlevel! == 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
... während die andere Syntax bei "ohne DelayedExpansion"/nur "Setlocal" richtig genannt wurde:
...
for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
IF ErrorLevel 1 echo Aktuelles Errorlevel: 1 oder größer
IF ErrorLevel 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
)
for /f "tokens=* delims=" %%a in (''%sidcheck%') do (
IF ErrorLevel 1 echo Aktuelles Errorlevel: 1 oder größer
IF ErrorLevel 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
)
--> hier als "IF ERRORLEVEL 1 " ohne die doppelten Gleichheitszeichen und ohne %- oder !-Zeichen um die Variable Errorlevel (also NICHT %errorlevel% und auch nicht !errorlevel!
Tut mir leid, dass Du da ganz umsonst so eine Schleife geflogen bist.
Dafür hast du bei Gelegenheit einen Oneliner gut bei mir.
Zerknirscht
Biber