luckypuncher
Goto Top

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

Content-Key: 126772

Url: https://administrator.de/contentid/126772

Printed on: April 25, 2024 at 13:04 o'clock

Member: TsukiSan
TsukiSan Oct 09, 2009 at 02:23:09 (UTC)
Goto Top
Hallo LuckyPuncher,

ändere doch mal:
echo %errorlevel%

in:
echo Errorlevel :%sidcheck%
und nimm mal in
(''%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
Member: LuckyPuncher
LuckyPuncher Oct 09, 2009 at 08:57:59 (UTC)
Goto Top
Hallo TsukiSan

Danke für die Rückmeldung.

ändere doch mal:
> echo %errorlevel%
> 

in:
> echo Errorlevel :%sidcheck%
> 

habe ich, bringt bei mir ledglich eine Ausgabe.

Errorlevel :psgetsid.exe \\DCNAME -u ADSDOMAIN\administrator -p password S-1-5-21-...
 

M.E muss die umgebungsvariable Errorlevel immer mit %errorlevel% angesprochen werden um nicht als normale Abfolge von Zeichen interpretiert zu werden.

Mein Problem ist, dass der Wert von %errorlevel% immer true ist, egal ob die Ausführung von PSGETSID.exe samt Paramtern zu einem Fehler geführt hat. Z.B. SID gibt es nicht.

Erst wenn %errorlevel% als solche richtig gesetzt wird, macht eine weitere Auswertung Sinn.

Gruß
LuckyPuncher
Member: TsukiSan
TsukiSan Oct 09, 2009 at 13:28:26 (UTC)
Goto Top
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
Member: rubberman
rubberman Oct 09, 2009 at 14:35:09 (UTC)
Goto Top
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
psgetsid.exe \\%dcname% -u %domainnb%\%adjoinUN% -p %adjoinPW% %usersid% &&goto Erfolg ||goto Fehler

Grüße
rubberman
Member: LuckyPuncher
LuckyPuncher Oct 09, 2009 at 15:01:33 (UTC)
Goto Top
Hallo rubberman!

der blosse Aufruf von Psgetsid.exe samt Parametern bringt in der Tat Errorlevels zurück. Das habe ich schon getesetet. in Kombination mit For klappts leider nicht mehr.
Die For Schleife brauche ich jedoch um weitere Aktionen mit der Rückgabe der PSGetsid.exe- Anfrage:
die DomänenuserSIDs weiterzuverwenden. Also lediglich der Errorlevel reicht leider nicht aus.

das sollte etwa weiter gemacht werden.
- wenn %errorcode% =1 dann sid/user auslassen, Eintrag in Logfile o-ä. und weitermachen in der Schleife
- wenn %errorcode% =0 dann mittels 'reg add' die DomänenSID unter HKlm\software\microsoft\windows nt\currentversion\profilelist eintragen.

Gruß
LuckyPuncher
Member: Biber
Biber Oct 09, 2009 at 17:34:18 (UTC)
Goto Top
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
...
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.
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 (
IF ErrorLevel 1 echo Aktuelles Errorlevel: 1 oder größer
IF ErrorLevel 1 ( machFehlerMeldung) ELSE machBissinessAsUhschl
)
..
Schönes Wochenende
Biber
Member: LuckyPuncher
LuckyPuncher Oct 12, 2009 at 17:04:19 (UTC)
Goto Top
Habe die Ehre Biber,

Vielen Dank für das Feedback.
das mit den delayedexpansion habe ich mir zu Gemüte geführt: macht Sinn und wäre schön, leider aber in NT4 nicht möglich. Es geht lediglich: setlocal enableextensions
also:
den Code von ODER ausprobiert: Leider hat das so nicht geklappt: Er bringt jedesmal den selben Errorcode (0).
Daher habe ich die Problematik umgangen und das Skript anders aufgebaut.
Jetzt fange ich in der For-Schleife nur SIDs mit Entsprechung ab. Diese übergebe ich an find um weiter zu filtern, Dann passe ich die Registry Profilliste um die zu migrierenden Benutzer an.

Naja, vielleicht kann das ja noch jemand mal ausser mir brauchen.

for /f %%i in ('dir /B /A:D C:\winnt\profiles ^| findstr /r /v ^.*00.$') do call :process %%i  
goto :eof

:process
set username=%1
if /I %username%==system         goto :cancel
if /I %username%==administrator  goto :cancel 
@for /f %%m in ('"psgetsid \\%dcname% -u %domainnb%\%adjoinUN% -p %adjoinPW% %username% 2>NUL |find /i "s-1-5-2""') do (  
if errorlevel = 1 (echo failure
) else (
REM The processed User must not be logged on 
REG ADD "HKLM\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\%%m\profileimagepath"=%username%.000>>C:\regedited.txt  
)
)
goto :eof

:cancel
@echo user %username% will not be migrated

:end

Gruß
LuckyPuncher
Member: Biber
Biber Oct 12, 2009 at 17:53:36 (UTC)
Goto Top
Uppps, sorry, LuckyPuncher,

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
)

--> 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