Many thanks Richard. It looks just what I need. ! Mark Abbiss
-----Original Message----- From: Puckett, Richard [mailto:[EMAIL PROTECTED]] Sent: Montag, 27. Januar 2003 16:19 To: [EMAIL PROTECTED] Subject: RE: [ActiveDir] Migrating Users from NT to W2K Mark, Below is a script I wrote last year as sort of a WMI proof-of-concept/learning experience that performs user profile redirection. It points a new userid (in this case, a migrated user in Active Directory) to an existing profile (their previous profile) on the same host. This may not be exactly what you are looking for, but many of the functions in this script can be used to direct a user's profile path at an alternate location. You might also consider populating the 'profile' attribute on the user object itself (using IADsUser in ADSI), if you were considering pointing the user at a custom location for profile information. Hope this helps, Richard ### BEGIN CODE ### '___________________________________________________________________________ _______ ' NAME: PROFILE.VBS - Profile Redirection Script ' ' REVISION: v1.0 10.18.2002 (script created) ' ' PURPOSE: When migrating workstations from one domain or forest to another, a new ' profile is generated for a user, often resulting in the loss of custom ' settings, legacy application configurations, and an overall look & feel ' of the desktop. By replacing the new profile path in the registry with ' the profile path of the previous userid, a user can (with the correct ' set of local privileges) continue to use their previous profile. ' ' HOW IT WORKS: ' ' 1. determine the string representations of both the old and new user identities ' (SIDs) by retrieving the binary sids from both domains and converting them to ' a string format (w/ WMI's Win32_Account class) ' 2. traverse the registry to SOFTWARE\Microsoft\Windows NT\CurrentVersion\ ' ProfileList\<old-string-sid-here> and retrieve the original ProfileImagePath ' value (which is the path to the actual profile) ' 3. locate (or add) the new user profile with SOFTWARE\Microsoft\Windows NT\ ' CurrentVersion\ProfileList\<new-string-sid-here>, then modify or add the ' ProfileImagePath value to include the old profile path you'd retrieved from ' the previous call. ' ' CAVEATS: ' ' 1. You'll need to be an administrator on both domains, and on the target host, ' in order to run this script. ' 2. Stored password data is not migrated, this was something I really haven't had ' time to look into, but I believe that any stored mail/web passwords are linked ' to the original user's SID. ' 3. Profile redirection can fail, but often just results in the creation of a new ' profile. ' 4. This method of profile redirection on W2K is currently unsupported by MSFT. ' ' DISCLAIMER: ' ' You have a royalty-free right to use, modify, reproduce and distribute this code ' (and/or any modified version) in any way you find useful, with the agreement ' that Richard Puckett provide no warranty, obligations or liability for this code. ' If you reuse or modify this code, you must retain this copyright notice. ' ' ' copyright (C) 2002 Richard Puckett '___________________________________________________________________________ _______ '___________________________________________________________________________ _______ ' variables, declares & constants '___________________________________________________________________________ _______ option explicit 'on error resume next ' declares dim lRet, lCheck, lCompare, lReboot dim strTarget, strWksUsr, strWksPwd dim strOldPDC, strOldDom, strOldUsr, strOldAct, strOldPwd, strOldSid, strOldProf dim strNewPDC, strNewDom, strNewUsr, strNewAct, strNewPwd, strNewSid, strNewProf dim objRegistry, strRegPath, strProfKey, strProfValue ' constants const HKEY_LOCAL_MACHINE = &H80000002 ' default registry path strRegPath = "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" strProfValue = "ProfileImagePath" ' set these values to conform to your environment ' target workstation information strTarget = "target_workstation_name" ' target workstation name strWksUsr = "userid (optional)" ' workstation userid (blank for impersonation) strWksPwd = "password (optional)" ' workstation password (blank for impersonation) ' target userid information for old (existing) profile strOldUsr = "target_userid" strOldAct = "domain\userid (optional)" ' old domain userid (blank for impersonation) strOldPwd = "password (optional)" ' old domain password (blank for impersonation) strOldPDC = "domain_controller_name" ' old domain controller name strOldDom = "domain_name" ' old domain name ' target userid information for new profile strNewUsr = "target_userid" strNewAct = "domain\userid (optional)" ' new domain userid (blank for impersonation) strNewPwd = "password (optional)" ' new domain password (blank for impersonation) strNewPDC = "domain_controller_name" ' new domain controller name strNewDom = "domain_name" ' new domain ' read-only check and remote reboot options lCheck = 1 ' set to 1 for a read-only comparision lReboot = 0 ' set to 1 to reboot the target workstation '___________________________________________________________________________ ______ ' ' START SCRIPT '___________________________________________________________________________ ______ wscript.echo "profile migration script started at " & Now & vbCRLF ' retrieve the string sid of the old userid from the previous account domain wscript.echo "attempting to retrieve a SID for " & strOldUsr & " on " & strOldDom & "..." strOldSid = get_sid(strOldUsr, _ strOldAct, _ strOldPwd, _ strOldDom, _ strOldPDC) wscript.echo " - the sid for " & strOldDom & "\" & strOldUsr & " is " & strOldSid wscript.echo "checking for the existence of a profile for " & strOldUsr & " on " & strTarget & "..." ' append the retrieve string sid the Registry profile key strProfKey = strRegPath & "\" & strOldSid ' attempt to read the remote registry for the existing user profile path information lRet = get_reg_val (strTarget, _ strWksUsr, _ strWksPwd, _ strProfKey, _ strProfValue, _ strOldProf) If lRet <> 0 Then If lRet = 2 Then ' the targeted existing profile path doesn't exist, barf and exit wscript.echo " - there does not appear to be a profile for " & strOldUsr & _ " on " & strTarget & vbCRLF & "Target Profile Key: " & strProfKey wscript.quit else ' some other error has occurred (most likely access-related), barf and exit wscript.echo " - error " & lRet & ": An error occurred attempting to access the profile for " & _ strOldUsr & " on " & strTarget & vbCRLF & "Target Profile Key: " & strProfKey wscript.quit end if else ' successfully retrieved the first set of values, now start on the second wscript.echo " - successfully retrieved the profile path for " & strOldUsr & " on " & strTarget & _ vbCRLF & " (" & strOldProf & ")" wscript.echo "attempting to retrieve a SID for " & strNewUsr & " on " & strNewDom & "..." ' attempt to retrieve the string sid of the new userid strNewSid = get_sid(strNewUsr, _ strNewAct, _ strNewPwd, _ strNewDom, _ strNewPDC) wscript.echo " - the sid for " & strNewDom & "\" & strNewUsr & " is " & strNewSid wscript.echo "checking for the existence of a profile for " & strNewUsr & " on " & strTarget & "..." ' append the new string sid to the Registry profile key strProfKey = strRegPath & "\" & strNewSid ' attempt to read the remote registry for the new user profile path information, if present lRet = get_reg_val (strTarget, _ strWksUsr, _ strWksPwd, _ strProfKey, _ strProfValue, _ strNewProf) If lRet = 0 Then wscript.echo " - successfully retrieved the profile path for " & strNewUsr & " on " & strTarget & _ vbCRLF & " (" & strNewProf & ")" wscript.echo "comparing the two profiles..." ' do a string comparison of the two returned profile paths lCompare = StrComp(strOldProf, strNewProf, 1) If lCompare <> 0 Then ' if different, check to see if this is a read-only comparision, if not, reset the profile path wscript.echo " - the two specified User Profile paths are different:" _ & vbCRLF & " desired (old) profile path - " & strOldProf _ & vbCRLF & " current (new) profile path - " & strNewProf ' read-only check if set to 1 if lCheck = 1 then wscript.echo " - read-only value detected, exiting...." wscript.echo "exiting script..." wscript.quit else wscript.echo "resetting the profile path for " & strNewUsr & "to " & _ strOldProf & " on " & strTarget & "..." ' attempt to write the existing profile path for the old userid to the new userid lRet = set_reg_val (strTarget, _ strWksUsr, _ strWksPwd, _ strProfKey, _ strProfValue, _ strOldProf) If lRet = 0 Then wscript.echo " - successfully reset the profile path for " & strNewUsr & " on " & _ strTarget & " to " & strOldProf ' bounce the remote target host if set to 1 if lReboot = 1 then wscript.echo "rebooting " & strTarget & "..." call bounce (strWksUsr, _ strTarget, _ strWksPwd) end if wscript.echo "exiting script..." wscript.quit else ' some other error has occurred (most likely access-related), barf and exit wscript.echo " - error " & lRet & ": unable to reset the profile path for " & _ strNewUsr & " on " & strTarget & " to " & strOldProf wscript.echo "exiting script..." wscript.quit end if end if else ' no change required, exit wscript.echo " - the two specified User Profile paths are the same:" _ & vbCRLF & " desired (old) profile path - " & strOldProf _ & vbCRLF & " current (new) profile path - " & strNewProf wscript.echo "exiting script..." wscript.quit end if else if lRet = 2 Then ' 2 is an expected return for most new profiles, it often means a user hasn't logged on yet wscript.echo " - there does not appear to be a profile for " & strNewUsr & _ " on " & strTarget & vbCRLF & " Target Profile Key: " & strProfKey ' if 1, read-only and exit if lCheck = 1 then wscript.echo " - read-only value detected, exiting...." wscript.echo "exiting script..." wscript.quit else wscript.echo "creating a new profile key for " & strNewUsr & " on " & strTarget & "..." ' attempt to create the new profile path key lRet = create_reg_key (strTarget, _ strWksUsr, _ strWksPwd, _ strProfKey) If lRet = 0 Then wscript.echo " - successfully created the profile key " & strProfKey & " for " & _ strNewUsr & " on " & strTarget wscript.echo "resetting the profile path for " & strNewUsr & " to " & _ strOldProf & "..." ' attempt to set the profile path value for the new profile key lRet = set_reg_val (strTarget, _ strWksUsr, _ strWksPwd, _ strProfKey, _ strProfValue, _ strOldProf) If lRet = 0 Then wscript.echo " - successfully reset the profile path for " & strNewUsr & " on " & _ strTarget & " to " & strOldProf ' reboot the host if set to 1 if lReboot = 1 then wscript.echo "rebooting " & strTarget & "..." call bounce (strWksUsr, _ strTarget, _ strWksPwd) end if wscript.echo "exiting script..." wscript.quit else ' some other error has occurred (most likely access-related), barf and exit wscript.echo " - error " & lRet & ": unable to reset the profile path for " & _ strNewUsr & " on " & strTarget & " to " & strOldProf wscript.echo "exiting script..." wscript.quit end if else ' some other error has occurred (most likely access-related), barf and exit wscript.echo " - error " & lRet & ": unable to create the profile key " & strProfKey & _ " for " & strNewUsr & " on " & strTarget wscript.echo "exiting script..." wscript.quit end if end if else ' some other error has occurred (most likely access-related), barf and exit wscript.echo " - error " & lRet & ": An error occurred attempting to access the profile for " & _ strNewUsr & " on " & strTarget & vbCRLF & " Target Profile Key: " & strProfKey wscript.echo "exiting script..." wscript.quit end if end if end if wscript.quit '___________________________________________________________________________ _______ ' WMI Functions '___________________________________________________________________________ _______ ' Create a Registry key in HKEY_LOCAL_MACHINE '___________________________________________________________________________ _______ ' function create_reg_key (strWksta, strUsr, strPwd, strRegKey) '___________________________________________________________________________ _______ dim objWbemLocator, objWmiCon, objReg, RetVal set objWbemLocator = CreateObject("WbemScripting.SWbemLocator") if len(strUsr) = 0 then set objWmiCon = objwbemLocator.ConnectServer _ (strWksta, _ "root\default") else set objWmiCon = objwbemLocator.ConnectServer _ (strWksta, _ "root\default", _ strUsr, _ strPwd) objWmiCon.Security_.AuthenticationLevel = 2 end if objWmiCon.Security_.ImpersonationLevel = 3 Set objReg = objWmiCon.Get("StdRegProv") RetVal = objReg.CreateKey (HKEY_LOCAL_MACHINE, _ strRegKey) create_reg_key = RetVal set objWbemLocator = Nothing set objWmiCon = Nothing set objReg = Nothing end function ' Set a REG_EXPAND_SZ value in HKEY_LOCAL_MACHINE '___________________________________________________________________________ _______ ' function set_reg_val (strWksta, strUsr, strPwd, strRegKey, strRegVal, strNewVal) '___________________________________________________________________________ _______ dim objWbemLocator, objWmiCon, objReg, RetVal set objWbemLocator = CreateObject("WbemScripting.SWbemLocator") if len(strUsr) = 0 then set objWmiCon = objwbemLocator.ConnectServer _ (strWksta, _ "root\default") else set objWmiCon = objwbemLocator.ConnectServer _ (strWksta, _ "root\default", _ strUsr, _ strPwd) objWmiCon.Security_.AuthenticationLevel = 2 end if objWmiCon.Security_.ImpersonationLevel = 3 Set objReg = objWmiCon.Get("StdRegProv") RetVal = objReg.SetExpandedStringValue (HKEY_LOCAL_MACHINE, _ strRegKey, _ strRegVal, _ strNewVal) set_reg_val = RetVal set objWbemLocator = Nothing set objWmiCon = Nothing set objReg = Nothing end function ' Read a REG_EXPAND_SZ value from HKEY_LOCAL_MACHINE '___________________________________________________________________________ _______ ' function get_reg_val (strWksta, strUsr, strPwd, strRegKey, strRegVal, strRegRet) '___________________________________________________________________________ _______ dim objWbemLocator, objWmiCon, objReg, RetVal set objWbemLocator = CreateObject("WbemScripting.SWbemLocator") if len(strUsr) = 0 then set objWmiCon = objwbemLocator.ConnectServer _ (strWksta, _ "root\default") else set objWmiCon = objwbemLocator.ConnectServer _ (strWksta, _ "root\default", _ strUsr, _ strPwd) objWmiCon.Security_.AuthenticationLevel = 2 end if objWmiCon.Security_.ImpersonationLevel = 3 Set objReg = objWmiCon.Get("StdRegProv") RetVal = objReg.GetExpandedStringValue (HKEY_LOCAL_MACHINE, _ strRegKey, _ strRegVal, _ strRegRet) get_reg_val = RetVal set objWbemLocator = Nothing set objWmiCon = Nothing set objReg = Nothing end function ' Retrieve a SID for a user using a WQL Query with Win32_Account '___________________________________________________________________________ _______ ' function get_sid (strAcct, strUsr, strPwd, strDom, strDC) '___________________________________________________________________________ _______ dim objWbemLocator, objWmiCon, objQuery, objSid, strQry set objWbemLocator = CreateObject("WbemScripting.SWbemLocator") strQry = "SELECT SID FROM Win32_Account WHERE Name = '" _ & strAcct & _ "' AND Domain = '" _ & strDom & "'" if len(strUsr) = 0 then set objWmiCon = objwbemLocator.ConnectServer _ (strDC, _ "root\cimv2") else set objWmiCon = objwbemLocator.ConnectServer _ (strDC, _ "root\cimv2", _ strUsr, _ strPwd) objWmiCon.Security_.AuthenticationLevel = 2 end if objWmiCon.Security_.ImpersonationLevel = 3 set objQuery = objWmiCon.ExecQuery(strQry, "WQL") for each objSid in objQuery get_sid = objSid.Sid next set objWbemLocator = Nothing set objWmiCon = Nothing set objQuery = Nothing set objSid = Nothing end function ' Reboot a target workstation '___________________________________________________________________________ _______ ' function bounce (strUsr, strPwd, strPC) '___________________________________________________________________________ _______ dim objWbemLocator, objWmiCon, objWMIos, objOS, strQry set objWbemLocator = CreateObject("WbemScripting.SWbemLocator") strQry = "SELECT * FROM Win32_OperatingSystem" if len(strUsr) = 0 then set objWmiCon = objwbemLocator.ConnectServer _ (strPC, _ "root\cimv2") else set objWmiCon = objwbemLocator.ConnectServer _ (strPC, _ "root\cimv2", _ strUsr, _ strPwd) objWmiCon.Security_.AuthenticationLevel = 2 end if objWmiCon.Security_.ImpersonationLevel = 3 objWmiCon.Security_.Privileges.AddAsString ("SeRemoteShutdownPrivilege") set objWMIos = objWmiCon.ExecQuery(strQry) For Each objOS in objWMIos ObjOS.Reboot() Next set objWbemLocator = Nothing set objWmiCon = Nothing set objWMIos = Nothing set objOS = Nothing end function ### END CODE ### > > > -----Original Message----- > From: Abbiss, Mark [mailto:[EMAIL PROTECTED]] > Sent: Monday, January 27, 2003 9:53 AM > To: '[EMAIL PROTECTED]' > > Dear All, > > We are about to embark on a phased migration of our users > from NT to W2K. We have a useful little program (SecureCopy) > that is excellent at moving files, folders, permissions etc > into the new domain but would now like to find a method, > other than doing it by hand, to modify the path to the > home/profile directories for the users being migrated. > > Does any one know of a (preferably free) tool/script that can > help us do this ? > > Many thanks, > > Mark Abbiss > List info : http://www.activedir.org/mail_list.htm > List FAQ : http://www.activedir.org/list_faq.htm > List archive: > http://www.mail-archive.com/activedir%40mail.activedir.org/ > List info : http://www.activedir.org/mail_list.htm List FAQ : http://www.activedir.org/list_faq.htm List archive: http://www.mail-archive.com/activedir%40mail.activedir.org/ List info : http://www.activedir.org/mail_list.htm List FAQ : http://www.activedir.org/list_faq.htm List archive: http://www.mail-archive.com/activedir%40mail.activedir.org/