Jump to content

User Profile Migration Tool


Recommended Posts

Good afternoon,

I hope someone can help me with a script I’m working on...

Background:

We have approximately 8000 workstation within our organisation and approximately half of them are members of a 2003 Active Directory Domain and we are trying to push the rest into the domain. Adding the workstations to the domain is not the problem, but the user profiles are… (We are talking a lot of crap here people!)

A previous employee managed to achieve this process using 'moveuser.exe' which is a part of the Windows 2003 Resource Kit and a combination of registry files, batch files and an autoit script. However he didn't anticipate problems with the profiles i.e. corruption or profile locks. We have UPHClean installed on the majority of our workstations but this only seems to work if the user logs in and out again for a profile clean up.

I have taken all of the above and tried to incorporate the processes into a single AutoIT Script.

The script works as follows:

If the ini file doesn't exist then UPMT opens the configuration GUI where you can customise the settings. Once you click OK this will generate the file (If you need to change it later on you can use the /CONFIG parameter.)

If used with the /CLEAN parameter, UPMT will search for User Profiles in the following location within the registry:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

If UPMT finds a RefCount DWORD value that is set to something other than '0' then UPMT resets it. (The current user logged in is excluded)

UPMT then joins the workstation to the Active Directory Domain

UPMT creates an entry in RunOnce to load itself with the /MIGRATE parameter.

UPMT also sets the AutoAdminLogon, DefaultUserName and DefaultPassword registry keys to allow it to perform the migration of profiles as a local administrator.

UPMT imports any additional registry settings if specified e.g. For the Novell Client

UPMT prompts user for a reboot.

When the workstation has rebooted it will automatically login and launch UPMT with the /MIGRATE parameter which starts the migration of profiles.

Once the migration is complete UPMT disables the AutoAdminLogin feature and removes the entries previously set from the registry.

UPMT imports another registry file (which can undo the previous entries imported)

UPMT reboots.

There is another parameter /JOIN which doesn't perform the profile cleanup operation. Instead it just joins the workstation to the domain and will start the migration of profiles on next reboot.

All good so far, but I would like the ability to exclude users from the migration e.g.

Administrator

helpdesk

etc...

This is the point where I'm stuck I can read the excluded users from the ini file but I can't get my head round what I need to do at this point...

Thanks in advance...

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=UPMT.ico
#AutoIt3Wrapper_outfile=UPMT.exe
#AutoIt3Wrapper_Res_Comment=This utility was created using AutoIT, created by Jonathan Bennett & the AutoIt Team and utilises a number of utilities from Microsoft e.g. moveuser.exe and netdom.exe
#AutoIt3Wrapper_Res_Description=User Profile Migration Tool
#AutoIt3Wrapper_Res_Fileversion=1.0.0.2
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
://////=__=.=
://////=__=.=
://////=__=
://////=__=...
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#Include <String.au3>
#include <ButtonConstants.au3>

Opt('GUIOnEventMode' , 1)
Opt('TrayIconHide', 1)

Global $App = "User Profile Migration Tool"
Global $INI_File = @ScriptDir & "\" & StringTrimRight(@ScriptName, 4) & ".ini"
Global $EncryptionKey = "AUTOITRULES!"

Global $guiLocalUSER, $guiLocalPWD, $guiDomainUSER, $guiDomainPWD, $guiDomain, $guiDomainOU, $guiExcluded, $guipremigrate, $guipostmigrate, $GUI

If NOT FileExists($INI_File) Then _SetConfig()

$message = "Please Wait..." & @CRLF & @CRLF & _
"Your account is being moved and if you attempt to close this box or reboot your PC, it will not function as expected and you are likely to lose files." & @CRLF & @CRLF & _
"Your PC will reboot itself when this process has finished." & @CRLF & @CRLF & _
"If you see this box for more than 10 minutes, please phone the helpdesk on xXXXXX and provide the following information:" & @CRLF & @CRLF & _
    "Computer Name: "& @ComputerName & @CRLF & _
    "IP Address: " & @IPAddress1

; Checking for command line switches
If $cmdline[0] > 0 Then
    Switch $cmdline[1]
        Case "/JOIN", "/join"
            _JoinDomain()
        Case "/CLEAN", "/clean"
            _CleanUpUserProfiles()
        Case "/MIGRATE", "/migrate"
            _MigrateProfiles()
        Case "/CONFIG", "/config"
            _SetConfig()
        Case "-?", "/?"
            MsgBox(0, $App & " - Help", @ScriptName & " /CONFIG = Opens configuration" & @CRLF & @CRLF & _
            @ScriptName & " /CLEAN = Performs following actions:" & @CRLF & _
            @TAB & "- Cleans up User Profiles" & @CRLF & _
            @TAB & "- Joins workstation to domain" & @CRLF & _
            @TAB & "- Migrates User Profiles" & @CRLF & @CRLF & _
            @ScriptName & " /JOIN = Performs following actions:" & @CRLF & _
            @TAB & "- Joins workstation to domain" & @CRLF & _
            @TAB & "- Migrates User Profiles" & @CRLF & @CRLF & _
            @ScriptName & " /MIGRATE = Performs following actions:" & @CRLF & _
            @TAB & "- Migrates User Profiles")
            Exit
        Case Else
            MsgBox(0, $App & " - Invalid Parameter!", "Please use " & @ScriptName & " /? for a list of parameters")
            Exit
    EndSwitch
;~ Else
;~  MsgBox(16, $App, "Command line parameter is required!" & @CRLF & @CRLF & "Please use " & @ScriptName & " /? for a list of parameters.")
;~  Exit
EndIf

Func _SetConfig()
    $GUI = GUICreate($App, 300, 500, -1, -1, $WS_BORDER);, $WS_EX_TOOLWINDOW)

; Local Authentication Details
    Local $LocalUSER = IniRead($INI_File, "Local", "Username", "")
    Local $LocalPWD = _StringEncrypt(0, IniRead($INI_File, "Local", "Password", ""), $EncryptionKey, 1)
; Domain Name
    Local $Domain = IniRead($INI_File, "Domain", "Domain", "")
; Domain Organisational Unit
    Local $DomainOU = IniRead($INI_File, "Domain", "DomainOU", "")
; Domain Authentication Details
    Local $DomainUSER = IniRead($INI_File, "Domain", "Username", "")
    Local $DomainPWD = _StringEncrypt(0, IniRead($INI_File, "Domain", "Password", ""), $EncryptionKey, 1)

    Local $ExcludeUser = StringReplace(IniRead($INI_File, "ExcludeUsers", "Users", ""), "|", @CRLF)

    Local $PreMigrate = IniRead($INI_File, "Actions", "PreMigrate", "")
    Local $PostMigrate = IniRead($INI_File, "Actions", "PostMigrate", "")

    GuiCtrlCreateGroup("Local Credentials", 5, 5, 285, 80)
    GuiCtrlCreateLabel("Username:", 15, 30)
    $guiLocalUSER = GuiCtrlCreateInput($LocalUSER, 80, 25, 200, 20)
    GuiCtrlCreateLabel("Password:", 15, 55)
    $guiLocalPWD = GuiCtrlCreateInput($LocalPWD, 80, 50, 200, 20, $ES_PASSWORD)

    GuiCtrlCreateGroup("Domain Credentials", 5, 90, 285, 80)
    GuiCtrlCreateLabel("Username:", 15, 115)
    $guiDomainUSER = GuiCtrlCreateInput($DomainUSER, 80, 110, 200, 20)
    GuiCtrlCreateLabel("Password:", 15, 140)
    $guiDomainPWD = GuiCtrlCreateInput($DomainPWD, 80, 135, 200, 20, $ES_PASSWORD)

    GuiCtrlCreateGroup("Domain", 5, 175, 285, 80)
    GuiCtrlCreateLabel("Domain:", 15, 200)
    $guiDomain = GuiCtrlCreateInput($Domain, 80, 195, 200, 20)
    GuiCtrlCreateLabel("W/S OU:", 15, 225)
    $guiDomainOU = GuiCtrlCreateInput($DomainOU, 80, 220, 200, 20)

    GuiCtrlCreateGroup("Excluded User(s) from migration", 5, 260, 285, 80)
    $guiExcluded = GuiCtrlCreateEdit($ExcludeUser, 15, 280, 265, 50, $ES_WANTRETURN + $ES_AUTOVSCROLL )

    GuiCtrlCreateGroup("Registry Changes", 5, 345, 285, 80)
    GuiCtrlCreateLabel("Pre-Migrate:", 15, 370)
    $guipremigrate = GuiCtrlCreateInput($PreMigrate, 80, 365, 170, 20)
    GUICtrlSetTip(-1, "Ensure that the *.reg file is located within the same location as " & @ScriptName)
    $btBrowse = GUICtrlCreateButton("...", 255, 365, 26, 18)
    GUICtrlSetOnEvent(-1,"_PreMigrateBrowse")

    GuiCtrlCreateLabel("Post Migrate:", 15, 395)
    $guipostmigrate = GuiCtrlCreateInput($PostMigrate, 80, 390, 170, 20)
    GUICtrlSetTip(-1, "Ensure that the *.reg file is located within the same location as " & @ScriptName)
    $btBrowse = GUICtrlCreateButton("...", 255, 390, 26, 18)
    GUICtrlSetOnEvent(-1,"_PostMigrateBrowse")

    $btOk = GUICtrlCreateButton("Ok", 75, 435, 70, -1, $BS_DEFPUSHBUTTON)
    GUICtrlSetOnEvent(-1,"_WriteConfig")

    $btCancel = GUICtrlCreateButton("Cancel", 155, 435, 70, -1)
    GUICtrlSetOnEvent(-1,"_Quit")

    While 1  ; Main script loop
        GUISetState()
        Sleep (10000)
    WEnd
EndFunc

Func _PreMigrateBrowse()
    Local $sTmpFile = FileOpenDialog("Select file:", @ScriptDir , "Registration Files (*.reg)")
    GUICtrlSetData($guipremigrate, StringRegExpReplace($sTmpFile, "^.+\\(.+)$", "$1")); GUI will be updated at next iteration
EndFunc

Func _PostMigrateBrowse()
    Local $sTmpFile = FileOpenDialog("Select file:", @ScriptDir , "Registration Files (*.reg)")
    GUICtrlSetData($guipostmigrate, StringRegExpReplace($sTmpFile, "^.+\\(.+)$", "$1")); GUI will be updated at next iteration
EndFunc

Func _WriteConfig()
    $sLocalUser = GUICtrlRead($guiLocalUSER)
    $sLocalPwd = _StringEncrypt(1, GUICtrlRead($guiLocalPWD), $EncryptionKey, 1)
    $sDomainUser = GUICtrlRead($guiDomainUSER)
    $sDomainPwd = _StringEncrypt(1, GUICtrlRead($guiDomainPWD), $EncryptionKey, 1)
    $sDomain = GUICtrlRead($guiDomain)
    $sDomainOU = GUICtrlRead($guiDomainOU)
    $sExcludeUser = StringReplace(GUICtrlRead($guiExcluded), @CRLF, "|")

    $sPreMigrate = GUICtrlRead($guipremigrate)
    $sPostMigrate = GUICtrlRead($guipostmigrate)

    IniWrite ($INI_File, "Actions", "PreMigrate", $sPreMigrate)
    IniWrite ($INI_File, "Actions", "PostMigrate", $sPostMigrate)

    IniWrite ($INI_File, "Local", "Username", $sLocalUser)
    IniWrite ($INI_File, "Local", "Password", $sLocalPwd)

    IniWrite ($INI_File, "Domain", "Domain", $sDomain)
    IniWrite ($INI_File, "Domain", "DomainOU", $sDomainOU)
    IniWrite ($INI_File, "Domain", "Username", $sDomainUser)
    IniWrite ($INI_File, "Domain", "Password", $sDomainPwd)

    IniWrite ($INI_File, "ExcludeUsers", "Users", $sExcludeUser)
    GUIDelete($GUI)
    Exit
EndFunc

Func _CleanUpUserProfiles()
    Local $iStart = 0, $sVal
    Local $sReg = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
    While 1
        $iStart += 1
        $sKey = RegEnumKey($sReg, $iStart)
        If @Error Then ExitLoop
        If StringMid($sKey, 7, 2) <> 21 Then ContinueLoop
        $sVal = RegRead($sReg & "\" & $sKey, "ProfileImagePath")
        $sUserProfile = StringRegExpReplace($sVal, "^.+\\(.+)$", "$1")
        If $sUserProfile <> @UserName Then
            $sRefCount=RegRead($sReg & "\" & $sKey, "RefCount")
            If $sRefCount <> 0 Then $sResetRefCount=RegWrite($sReg & "\" & $sKey, "RefCount", "REG_DWORD", 0)
            If @error <> 0 AND @error <> 1 Then MsgBox(16, $App, "An error has occurred while attempting to reset a user profile." & @CRLF & @CRLF & "User Profile: " & $sUserProfile & @CRLF & "Error Code: " & @error)
        EndIf
    WEnd
    _JoinDomain()
EndFunc   ;==>_CleanUpUserProfiles

Func _JoinDomain()

    Local $PreMigrate = IniRead($INI_File, "Actions", "PreMigrate", "")

    Local $LocalUSER = IniRead($INI_File, "Local", "Username", "")
    Local $LocalPWD = _StringEncrypt(0, IniRead($INI_File, "Local", "Password", ""), $EncryptionKey, 1)

    Local $setDomainOU
    Local $Domain = IniRead($INI_File, "Domain", "Domain", "")
    Local $DomainOU = IniRead($INI_File, "Domain", "DomainOU", "")
    Local $DomainUSER = IniRead($INI_File, "Domain", "Username", "")
    Local $DomainPWD = _StringEncrypt(0, IniRead($INI_File, "Domain", "Password", ""), $EncryptionKey, 1)

    If $DomainOU <> "" Then $setDomainOU = " /OU:"  ; Sets the Domain OU of where to add a computer account if specified within the ini file.

    Msgbox(0,"Debug", "netdom.exe join " & @ComputerName & " /Domain:" & $Domain & $setDomainOU & $DomainOU & " /UserD:" & $DomainUSER & " /PasswordD:" & $DomainPWD & " >C:\Migrate.log")
;~  RunWait(@Comspec & " /c netdom.exe join " & @ComputerName & " /Domain:" & $Domain & $setDomainOU & $DomainOU & " /UserD:" & $DomainUSER & " /PasswordD:" & $DomainPWD & " >C:\Migrate.log", @ScriptDir, @SW_MINIMIZE)   ;
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce", "UPMT", "REG_SZ", """" & @ScriptFullPath & """ /MIGRATE")
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "AutoAdminLogon", "REG_SZ", 1)
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultUserName", "REG_SZ", $LocalUSER)
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultPassword", "REG_SZ", $LocalPWD)

    If $PreMigrate <> "" Then RunWait("regedit -s " & $PreMigrate, @ScriptDir)

    If (MsgBox(33, $App & " - Reboot Required", "Your computer has just joined to the " & $Domain & " domain." & @CRLF & @CRLF & "On next reboot, all user profiles (your settings) will be migrated which may take some time." & @CRLF & @CRLF & "Press OK to reboot now, or Cancel to return to Windows." & @CRLF & "If you click Cancel, please reboot over lunch or as you leave this evening.") = 1) Then
        MsgBox(0, "DEBUG", "Restart")
;~      Shutdown(22)  ;Force or force if hung a reboot
    EndIf
EndFunc

Func _MigrateProfiles()

    Local $PostMigrate = IniRead($INI_File, "Actions", "PostMigrate", "")
    Local $Domain = IniRead($INI_File, "Domain", "Domain", "")
    $Domain = StringLeft($Domain, (StringInStr($Domain, ".")-1))
    If $Domain <> "" Then
        $Domain = $Domain & "\"
    Else
        Msgbox(16, $App, "The domain has not been specified or is not fully qualified." & @CRLF & @CRLF & "Please run " & @ScriptName & " /CONFIG and make the necessary changes.")
        Exit
    EndIf

    Local $ExcludeUser= StringSplit(IniRead($INI_File, "ExcludeUsers", "Users", ""), "|")

    SplashTextOn($App, $message, -1, 220, -1, -1, 20,"Arial",10)
    RegDelete("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "AutoAdminLogon")
    RegDelete("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultPassword")
    If $PostMigrate <> "" Then RunWait("regedit -s " & $PostMigrate, @ScriptDir)

    Local $iStart = 0, $sVal
    Local $sReg = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
    While 1
        $iStart += 1
        $sKey = RegEnumKey($sReg, $iStart)
        If @Error Then ExitLoop
        If StringMid($sKey, 7, 2) <> 21 Then ContinueLoop
        $sVal = RegRead($sReg & "\" & $sKey, "ProfileImagePath")
        $sUserProfile = StringRegExpReplace($sVal, "^.+\\(.+)$", "$1")

; <====== STUCK HERE ======>
;~      If IsArray($ExcludeUser) Then
;~          For $i = 1 to $ExcludeUser[0]
;~              If $sUserProfile <> $ExcludeUser[$i] Then
;~              MsgBox(0, $App, $ExcludeUser[$i])
;~          Next
;~      EndIf

        If $sUserProfile <> @UserName Then Msgbox(0,"Debug", "moveuser.exe " & $sUserProfile & " " & $Domain & $sUserProfile, @ScriptDir)
        ;RunWait(@Comspec & " /c moveuser.exe " & $sUserProfile & " " & $Domain & $sUserProfile, @ScriptDir)

    WEnd

    SplashOff()

    MsgBox(0, "DEBUG", "Restart")
;~  Shutdown(22)  ;Force or force if hung a reboot
    Exit
EndFunc

Func _Quit()
    GUIDelete($GUI)
    Exit
EndFunc

Exit
Edited by PlayZoneUK

Words of Wisdom and Favourite Quotes:

'Nothing is impossible, despite what other people say and think, prove them wrong and show them what you can do!'

'Understanding is a three edged sword, your side, their side and the truth!'

'The truth that humanity has never been able to grasp, is that death may be the only absolute freedom there is!'

'I've run out of places to put the brush... what do you suggest?'

Link to comment
Share on other sites

I know I can achieve my objective if I hard code the usernames into my script:

If $sUserProfile <> @UserName AND $sUserProfile <> "administrator" AND $sUserProfile <> "helpdesk" Then RunWait(@Comspec & " /c moveuser.exe " & $sUserProfile & " " & $Domain & $sUserProfile, @ScriptDir)

However I would like the ability to customise from an ini file incase I need to add any additional accounts in the future, I'm just not sure how to implement this...

any help will be much appreciated

Words of Wisdom and Favourite Quotes:

'Nothing is impossible, despite what other people say and think, prove them wrong and show them what you can do!'

'Understanding is a three edged sword, your side, their side and the truth!'

'The truth that humanity has never been able to grasp, is that death may be the only absolute freedom there is!'

'I've run out of places to put the brush... what do you suggest?'

Link to comment
Share on other sites

1st to answer your immediate question. each profile in the ProfileList key you are already looking at has a ProfileImagePath value with the path to the profile for each user that has logged in to the computer. Loop the ProfileList using the RegEnum functions and compare this value to your ini file values and skip over profiles you need.

2nd I'm curious about the details of the migration. I just wrote a nice migration script to eliminate Novell and migrate to a windows domain with active directory.

It was a pretty brilliant script that actually assigned the old novell windows profile to the new domain user and took care of all permissions issues as well. This saved tons of time copying profiles and migrating the old ones once a new domain user has logged in. The only side effect is the users have a profile named in our old naming scheme (last name 1st initial) but login with the new AD user name (their ID). The benefits were that it was much quicker and that from a user standpoint everything looked the same, even desktop icon placement. If I can help with any of the specifics let me know.

Link to comment
Share on other sites

OK, here is an example of getting the list of user profiles. Understand this is written for XP, so you may need to make changes for Windows 7 or Vista. You will see at the beginning of the script I put in a trap to look for the OS. In this example, I'm looking for just Windows XP.) You can add more traps for the other OSs in your environment.

Anything you have listed in the INI will be EXCLUDED from the array. That way you can have a master list of profiles you do not wish to migrate.

#include <Array.au3>
$Q=2 ; set to 1 to write INI. Set to 2 to read INI. This is to just save you time
     ; writing the ini file.
DIM $users[1]
$search = -1 ; to allow for OS other than ones specified
IF @OSVersion = "WIN_XP" then
$search = FileFindFirstFile("C:\Documents and Settings\*")  
endif
If $search = -1 Then
    MsgBox(0, "Error", "No files/directories matched the search pattern")
    Exit
EndIf

If $Q=1 then
$x=1    
While 1
    $file = FileFindNextFile($search) 
    If @error Then ExitLoop
    IniWrite("userlist.ini", "1", $x, $file)
    $x=$x+1
    ConsoleWrite($file & @cr) ; shows what is found in the console area if you 
                              ; run the script in SciTE
WEnd
endif
If $q = 2 then 

While 1
    $file = FileFindNextFile($search) 
    If @error Then ExitLoop
    _ArrayAdd($users, $file)
WEnd
endif 

FileClose($search)
_ArrayDelete($users, 0)
$ini = IniReadSection("userlist.ini", "1") ;If the listing is found in the INI, then 
                                           ;it is remove from the array.
For $i = 1 to $ini [0][0]
    $search = _ArraySearch($users, $ini[$i][1])
    if $search <> -1 then _ArrayDelete($users, $search)
Next
_ArrayDisplay($users) ;list of users who meet the criteria.

For $r = 0 to UBound($users)
$sUserProfile = $users ;so you can reference the variable in your script
RunWait(@Comspec & " /c moveuser.exe " & $sUserProfile & " " & $Domain & $sUserProfile, @ScriptDir)
next
Edited by MPH
Link to comment
Share on other sites

@MFH

Thanks for pointing me in the right direction MFH, I believe I can incorporate some of the features within the example into my script. I'll give it ago tomorrow when I get into work and post the results / the finished product.

@ShawnW

Our organisation was purely a Novell eDirectory site, we utilised Novell ZENworks 6.5 for Desktops to create Dynamic Local User Profiles on the workstations. A 2003 Active Directory Domain was implemented approximately 6 years ago. Recently there has been a push to get all of our workstations into the domain, to help achieve this objective some workstations have been replaced or re-imaged. However some workstations which don't warrant replacement and can't be re-imaged (for what ever reason) have been added to the domain manually but the users loose their settings. Hence the creation of the User Profile Migration Tool I'm working on.

It looks like we'll be keeping Novell for the moment as we are utilising Novell's Identity Manager solution to synchronise the usernames and passwords between eDirectory and Active Directory therefore our naming conversion remains the same for our usernames (last name and 1st initial)

Since you've already experienced this issue and have created some scripts in order to resolve it, would it be possible to have a look at them to point me in the right direction and ensure I'm on the right track?

Words of Wisdom and Favourite Quotes:

'Nothing is impossible, despite what other people say and think, prove them wrong and show them what you can do!'

'Understanding is a three edged sword, your side, their side and the truth!'

'The truth that humanity has never been able to grasp, is that death may be the only absolute freedom there is!'

'I've run out of places to put the brush... what do you suggest?'

Link to comment
Share on other sites

I'll post some code tomorrow on how look up a domain users sid, assign the domain user to an existing physical profile, and then resolve the permissions issues involved with this. This will allow a user to seemlessly transfer to the domain and start logging in with those credentials but still use the same profile they were using before. I would do it now but I gotta leave, and can't blindly post the source without making sure it doesn't reveal anything job sensitive.

Link to comment
Share on other sites

@ShawnW that would be fantastic if you could it would really help me out of a bind

Words of Wisdom and Favourite Quotes:

'Nothing is impossible, despite what other people say and think, prove them wrong and show them what you can do!'

'Understanding is a three edged sword, your side, their side and the truth!'

'The truth that humanity has never been able to grasp, is that death may be the only absolute freedom there is!'

'I've run out of places to put the brush... what do you suggest?'

Link to comment
Share on other sites

Okay here it goes. Meant to post this eariler but forgot about a meeting in the morning.

The basic concept is...

To figure out what sid a user will have on the new domain, and replace their current ProfileList entry with that value. This lets the user login after a domain migration and get the same profile they had before. Lots of little things like permissions need to be handled as well.

External programs/scripts I used:

reg.au3 by Erik Pilsits (can be found in these forums).

SetAcl (google it).

psgetsid from the PSTools set of utilities (google it).

icacls (unnecessary with SetAcl but I commented why I used this).

Notes:

This was done on Windows XP SP3 machines.

Just use it as a guide since I wrote it specificlly for our unique setup, it won't run for anyone as is.

Logger("--- Transferring profiles Loop ---","_step2")
$n=1
$ProfileList = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\"
;========================================
;= Loop through ProgileList in registry =
;========================================
While True
    ;=================
    ;= Read Registry =
    ;=================
    $regSID = RegEnumKey($ProfileList,$n)                               ; Read next local profile from registry
    If @error Then ExitLoop                                             ; Exit loop if no more profile subkeys
    $profilePath = RegRead($ProfileList & $regSID, "ProfileImagePath")  ; Read the profiles path
    
    ;==================================================================================
    ;= If the profile sid does not contain the sid from UNT domain...                 =
    ;=   1) Match the old user name to a new one.                                     =
    ;=   2) Get the UNT domain sid for the new user name.                             =
    ;=   3) Rename(Move) the old sid named key to the new sid key for the UNT domain. =
    ;=   4) Change the binary sid value of this ley.                                  =
    ;=   5) Give permissions for domain user to proper registry areas                 =
    ;==================================================================================
    If Not StringInStr($regSID,"3676313182-2055043702-2189418671") Then ; The number is the 3 sets of the user sid after S-1-5-21-
        $NovellUser = StringRegExp($profilePath,".*\\(.*)",1)   ; Get the Novell user name from the end of the profile path
        $euid = GetEUID($NovellUser[0])                         ; Match the Novell user with their EUID
        $sid = ""                                               ; Default $sid
        
        Logger("-- Processing user profile " & $NovellUser[0] & " --","_step2")
        If $euid <> "-na-" Then
            Logger("Matched Novell user profile " & $NovellUser[0] & " to UNT user name " & $euid,"_step2")
            
            ;===========================================================
            ;= Set Permissions for new user name on old user directory =
            ;===========================================================
            Logger'Setting permissions for new user name on old user directory',"_step2")
            RunWait('p:\Faculty\Util\icacls.exe "' & $profilePath & '" /Grant:r UNT\' & $euid & ':(OI)(CI)F')
            ; ...I know I could use setacl here since I use it later for the registry, but I already had this written
            ; when I discovered I needed to change registry permissions and didn't feel like going back to change it.
            
            ;============================================================
            ;= Get the UNT domain SID for the matched EUID as user name =
            ;============================================================
            $sid = GetSID($euid)
            If $sid Then
                Logger("Found UNT domain SID for " & $euid & " (" & $sid & ")","_step2")
            Else
                Logger("### ERROR ### - Cound not find UNT domain SID for " & $euid,"_step2")
            EndIf
            
            ;======================================================================
            ;= If the unt domain profile for the found sid does not already exist =
            ;======================================================================
            If Not _RegKeyExists($ProfileList & $sid) Then
                ;===============================================================
                ; Transfer the current profile to its matching unt domain user =
                ; by moveing the old user SID registry key to the new UNT one  =
                ;===============================================================
                Logger("Transferring the current profile for " & $NovellUser[0] & " to UNT\" & $euid,"_step2")
                _RegMoveKey($ProfileList & $regSID,$ProfileList & $sid)
                
                ;=================================================================================================================
                ;= ... When we ran this script I noticed that _RegMoveKey was not actually deleting old key as expected.         =
                ;= I didn't think this was a problem until a few users started accidently logging into their old account.        =
                ;= I would recommend making sure the old key is gone at this point. But who knows the function may work for you. =
                ;=================================================================================================================

                ;====================================================================
                ;= Update the binary Sid registry value for the transferred profile =
                ;====================================================================
                Logger("Updating the binary Sid value for the transferred profile","_step2")
                $userSidSegment = StringRegExp($sid,".*-(.*)",1)                                                    ; Get the last part of the sid which identifies a user
                $hex = Hex($userSidSegment[0])                                                                      ; Transform this into a Hexadecimal number
                $hexString = StringRight($hex,2) & StringMid($hex,5,2) & StringMid($hex,3,2) & StringLeft($hex,2)   ; Reverse the Hex, 2 bits at a time Ex. 12345678 -> 78563412
                RegWrite($ProfileList & $sid,"Sid","REG_BINARY","0x0105000000000005150000005E1620DB767A7D7AAFE07F82" & $hexString)
                ; ...The 1st part of that string I copied from another user already created on that domain.
                ; It will be the same for all users in the domain and only the last 8 digits refer to the user.
                
                ;==================================
                ;= Load user hive to the registry =
                ;==================================
                $tempKey = "HKEY_USERS\temp"
                Logger("Loading the user hive Located in " & $profilePath & "\NTUSER.DAT")
                RunWait(@comspec & ' /c reg load HKU\Temp "' & $profilePath & '\NTUSER.DAT"')

                ;=================================
                ;= Give registry key permissions =
                ;=================================
                Logger("Giving UNT\" & $euid & " Full permissions to the loaded user hive")
                RunWait(@comspec & ' /c P:\Faculty\Batch\SetACL.exe -on "\\' & @ComputerName & '\' & $tempKey & '" -ot reg -actn ace -ace "n:UNT\' & $euid & ';p:full" -rec yes')
                Logger("Giving UNT\" & $euid & " Special permissions to " & $ProfileList & $sid,"_step2")
                RunWait(@comspec & ' /c P:\Faculty\Util\SetACL.exe -on "\\' & @ComputerName & '\' & $ProfileList & $sid & '" -ot reg -actn ace -ace "n:UNT\' & $euid & ';p:query_val,set_val,create_subkey,enum_subkeys,notify,create_link,delete,read_access" -rec yes')
                
                ; ...Removed some code others probably wont need that removes any persistant, user mapped, network drives to locations on our old servers.

                ;====================
                ;= Unload user hive =
                ;====================
                Logger("Unloading the user hive","_step2")
                RunWait(@comspec & ' /c reg unload HKU\Temp')
            Else
                Logger("### NOTICE ### - Registry key already exists (" & $ProfileList & $sid & ")","_step2")
            EndIf
        Else
            Logger("### ERROR ### - No matching UNT domain user name for Novell user profile " & $NovellUser[0],"_step2")
        EndIf
        Logger("-- Completed " & $NovellUser[0] & " --","_step2")
    EndIf
    $n += 1
WEnd
Logger("--- End Transferring profiles Loop ---","_step2")
Logger("----- Migration Step 2 Completed! Restarting Computer -----","_step2")
MsgBox(0,"Shutdown","System Restarting in 5 seconds.",5)
Shutdown(2)

;============================================================================================================
;====                                         ADDITINAL FUNCTIONS                                        ====
;============================================================================================================
; Logger calls a logger script we created to standardize our log format and location for all scripts.
; It also displays a tooltip in the corner to let the person running the scipt easily track it's progress.
Func Logger($text,$LogNameAppend="")
    $directory="Novell Migration\"
    If $text = "" Then Return
    ToolTip($text,0,0)
    RunWait("\\cob-static\apps\Faculty\Batch\logger.exe """ & $text & """ """ & $directory & @ComputerName & $LogNameAppend & ".txt""")
EndFunc

; GetEUID looks at a previously generated text file with matches for old to new names.
; All new user names are the users euid except multi-user accounts.
Func GetEUID($userName)
    $userName = StringRegExpReplace($userName,"\..*","")
    If StringRegExp($userName,"^[a-zA-z]{2,3}\d{4}$") Then Return $userName
    $file = FileRead("N:\Scripts\Novell2EUID.txt")
    $userMatch = StringRegExp($file, "(?i)" & $userName & ",(.*?)\r\n",1)
    If @error Then Return "-na-"
    Return $userMatch[0]
EndFunc

; GetSID uses a Pstools utility psgetsid to look up the sid for an existing UNT domain user.
; The user needs to have been created on the domain but does not need to have logged into any computer.
Func GetSID($userEUID)
;~  If $userEUID = "LocalSupport" Then Return "S-1-5-21-1731668739-84674044-697575874-1093"
; ...Commented this out for forum post because I honestly can't remember why I needed this exception, but noting exceptions might be required.
    $temp = @TempDir & "\temp.txt"
    RunWait(@ComSpec & ' /c ' & 'N:\SUPER\UTILITY\Pstools\psgetsid UNT\' & $userEUID & ' > ' & $temp,'',@SW_HIDE)
    $sid = FileReadLine($temp,2)
    If StringLeft($sid,9) <> "S-1-5-21-" Then $sid = "" ; Validate SID
    If FileExists($temp) Then FileDelete($temp)
    Return $sid
EndFunc
Link to comment
Share on other sites

Sorry for not replying to you sooner ShawnW...

Thank you for posting your script I will use it as a guide as you suggested. As previously posted we haven't changed our naming convention so it doesn't need to be advanced as yours ... Fortunately the moveuser.exe utility which comes with the Windows 2003 Resource Kit sorts out the permissions issues so I don't have to utilise any other utilities.

NOTE: Our target OS = Windows XP Service Pack 3

Hopefully I'll post the finished product in a few days

Words of Wisdom and Favourite Quotes:

'Nothing is impossible, despite what other people say and think, prove them wrong and show them what you can do!'

'Understanding is a three edged sword, your side, their side and the truth!'

'The truth that humanity has never been able to grasp, is that death may be the only absolute freedom there is!'

'I've run out of places to put the brush... what do you suggest?'

Link to comment
Share on other sites

  • 1 month later...

Sorry for not replying to you sooner ShawnW...

Thank you for posting your script I will use it as a guide as you suggested. As previously posted we haven't changed our naming convention so it doesn't need to be advanced as yours ... Fortunately the moveuser.exe utility which comes with the Windows 2003 Resource Kit sorts out the permissions issues so I don't have to utilise any other utilities.

NOTE: Our target OS = Windows XP Service Pack 3

Hopefully I'll post the finished product in a few days

Any luck with this? i am very interested in seeing your final results.

cheers,

robin850

Link to comment
Share on other sites

  • 1 month later...

Any luck with this? i am very interested in seeing your final results.

cheers,

robin850

Sorry robin850 I've just seen your post. The source code is on my network drive at work, I will post it tomorrow for those of you who are interested...

Words of Wisdom and Favourite Quotes:

'Nothing is impossible, despite what other people say and think, prove them wrong and show them what you can do!'

'Understanding is a three edged sword, your side, their side and the truth!'

'The truth that humanity has never been able to grasp, is that death may be the only absolute freedom there is!'

'I've run out of places to put the brush... what do you suggest?'

Link to comment
Share on other sites

  • 2 months later...
  • 1 month later...

Sorry for the long delay... enjoy

#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_icon=UPMT.ico
#AutoIt3Wrapper_outfile=UPMT.exe
#AutoIt3Wrapper_Res_Comment=This utility was created using AutoIT, created by Jonathan Bennett & the AutoIt Team and utilises a number of utilities from Microsoft e.g. moveuser.exe and netdom.exe
#AutoIt3Wrapper_Res_Description=User Profile Migration Tool
#AutoIt3Wrapper_Res_Fileversion=1.0.0.99
#AutoIt3Wrapper_Res_Fileversion_AutoIncrement=y
#AutoIt3Wrapper_Res_LegalCopyright=© 2010 PlayZoneUK
://////=__=.=
://////=__=.=
://////=__=
://////=__=...
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****

#include <WindowsConstants.au3>
#include <EditConstants.au3>
#include <GUIConstantsEx.au3>
#Include <String.au3>
#include <ButtonConstants.au3>
#include <Array.au3>
#include <Process.au3>
#Include <Date.au3>
#include <ProgressConstants.au3>

Opt('GUIOnEventMode' , 1)
#NoTrayIcon

Global $App = "User Profile Migration Tool"
Global $INI_File = @ScriptDir & "\" & StringTrimRight(@ScriptName, 4) & ".ini"
Global $EncryptionKey = "AUTOITRULES"

Global $guiLocalUSER, $guiLocalPWD, $guiDomainUSER, $guiDomainPWD, $guiDomain, $guiDomainOU, $guiExcluded, $guipremigrate, $guipostmigrate, $GUI

DIM $IncludeUser[1]

If NOT FileExists($INI_File) Then _SetConfig()

$message = "The user profiles on this workstation are migrating to the domain (your settings)..." & @CRLF & @CRLF & _
"WARNING:" & @CRLF &"If you attempt to close this box or reboot your PC, it will not function as expected and you are likely to lose files." & @CRLF & @CRLF & _
"Your PC will automatically reboot itself when this process has finished." & @CRLF & @CRLF & _
"It is likely that this process will take 10 minutes per profile. If it appears to be taking longer, please phone the helpdesk on x26655 and provide the following information:" & @CRLF & @CRLF & _
    "Computer Name: "& @ComputerName & @CRLF & _
    "IP Address: " & @IPAddress1

If @OSVersion <> "WIN_XP" Then
    Msgbox(16, $App, "The " & $App & " has been designed for Microsoft Windows XP only." & @CRLF & @CRLF & "Please contact your system administrator.", 30)
    Exit
EndIf

; Checking for command line switches
If $cmdline[0] > 0 Then
    Switch $cmdline[1]
        Case "/JOIN", "/join"
            _JoinDomain()
        Case "/CLEAN", "/clean"
            _CleanUpUserProfiles()
        Case "/MIGRATE", "/migrate"
            _MigrateProfiles()
        Case "/CONFIG", "/config"
            _SetConfig()
        Case "-?", "/?"
            MsgBox(0, $App & " - Help", @ScriptName & " /CONFIG = Opens configuration" & @CRLF & @CRLF & _
            @ScriptName & " /CLEAN = Performs following actions:" & @CRLF & _
            @TAB & "- Cleans up User Profiles" & @CRLF & _
            @TAB & "- Joins workstation to domain" & @CRLF & _
            @TAB & "- Migrates User Profiles" & @CRLF & @CRLF & _
            @ScriptName & " /JOIN = Performs following actions:" & @CRLF & _
            @TAB & "- Joins workstation to domain" & @CRLF & _
            @TAB & "- Migrates User Profiles" & @CRLF & @CRLF & _
            @ScriptName & " /MIGRATE = Performs following actions:" & @CRLF & _
            @TAB & "- Migrates User Profiles")
            Exit
        Case Else
            MsgBox(0, $App & " - Invalid Parameter!", "Please use " & @ScriptName & " /? for a list of parameters")
            Exit
    EndSwitch
EndIf

Func _SetConfig()
    $GUI = GUICreate($App, 300, 500, -1, -1, $WS_BORDER);, $WS_EX_TOOLWINDOW)

; Local Authentication Details
    Local $LocalUSER = IniRead($INI_File, "Local", "Username", "")
    Local $LocalPWD = _StringEncrypt(0, IniRead($INI_File, "Local", "Password", ""), $EncryptionKey, 1)
; Domain Name
    Local $Domain = IniRead($INI_File, "Domain", "Domain", "")
; Domain Organisational Unit
    Local $DomainOU = IniRead($INI_File, "Domain", "DomainOU", "")
; Domain Authentication Details
    Local $DomainUSER = IniRead($INI_File, "Domain", "Username", "")
    Local $DomainPWD = _StringEncrypt(0, IniRead($INI_File, "Domain", "Password", ""), $EncryptionKey, 1)

    Local $ExcludedUser = ""

    Local $PreMigrate = IniRead($INI_File, "Actions", "PreMigrate", "")
    Local $PostMigrate = IniRead($INI_File, "Actions", "PostMigrate", "")

    GuiCtrlCreateGroup("Local Credentials", 5, 5, 285, 80)
    GuiCtrlCreateLabel("Username:", 15, 30)
    $guiLocalUSER = GuiCtrlCreateInput($LocalUSER, 80, 25, 200, 20)
    GuiCtrlCreateLabel("Password:", 15, 55)
    $guiLocalPWD = GuiCtrlCreateInput($LocalPWD, 80, 50, 200, 20, $ES_PASSWORD)

    GuiCtrlCreateGroup("Domain Credentials", 5, 90, 285, 80)
    GuiCtrlCreateLabel("Username:", 15, 115)
    $guiDomainUSER = GuiCtrlCreateInput($DomainUSER, 80, 110, 200, 20)
    GuiCtrlCreateLabel("Password:", 15, 140)
    $guiDomainPWD = GuiCtrlCreateInput($DomainPWD, 80, 135, 200, 20, $ES_PASSWORD)

    GuiCtrlCreateGroup("Domain", 5, 175, 285, 80)
    GuiCtrlCreateLabel("Domain:", 15, 200)
    $guiDomain = GuiCtrlCreateInput($Domain, 80, 195, 200, 20)
    GuiCtrlCreateLabel("W/S OU:", 15, 225)
    $guiDomainOU = GuiCtrlCreateInput($DomainOU, 80, 220, 200, 20)

    GuiCtrlCreateGroup("Excluded User(s) from migration", 5, 260, 285, 80)
    $guiExcluded = GuiCtrlCreateEdit("Please configure the ini file manually for Excluded Users", 15, 280, 265, 50, $ES_WANTRETURN + $ES_AUTOVSCROLL )
;~  GUICtrlSetTip(-1, "Please configure the ini file manually for Excluded Users")
    GUICtrlSetState(-1, $GUI_DISABLE)

    GuiCtrlCreateGroup("Registry Changes", 5, 345, 285, 80)
    GuiCtrlCreateLabel("Pre-Migrate:", 15, 370)
    $guipremigrate = GuiCtrlCreateInput($PreMigrate, 80, 365, 170, 20)
    GUICtrlSetTip(-1, "Ensure that the *.reg file is located within the same location as " & @ScriptName)
    $btBrowse = GUICtrlCreateButton("...", 255, 365, 26, 18)
    GUICtrlSetOnEvent(-1,"_PreMigrateBrowse")

    GuiCtrlCreateLabel("Post Migrate:", 15, 395)
    $guipostmigrate = GuiCtrlCreateInput($PostMigrate, 80, 390, 170, 20)
    GUICtrlSetTip(-1, "Ensure that the *.reg file is located within the same location as " & @ScriptName)
    $btBrowse = GUICtrlCreateButton("...", 255, 390, 26, 18)
    GUICtrlSetOnEvent(-1,"_PostMigrateBrowse")

    $btOk = GUICtrlCreateButton("Ok", 75, 435, 70, -1, $BS_DEFPUSHBUTTON)
    GUICtrlSetOnEvent(-1,"_WriteConfig")

    $btCancel = GUICtrlCreateButton("Cancel", 155, 435, 70, -1)
    GUICtrlSetOnEvent(-1,"_Quit")

    While 1  ; Main script loop
        GUISetState()
        Sleep (10000)
    WEnd
EndFunc

Func _PreMigrateBrowse()
    Local $sTmpFile = FileOpenDialog("Select file:", @ScriptDir , "Registration Files (*.reg)")
    GUICtrlSetData($guipremigrate, StringRegExpReplace($sTmpFile, "^.+\\(.+)$", "$1")); GUI will be updated at next iteration
EndFunc

Func _PostMigrateBrowse()
    Local $sTmpFile = FileOpenDialog("Select file:", @ScriptDir , "Registration Files (*.reg)")
    GUICtrlSetData($guipostmigrate, StringRegExpReplace($sTmpFile, "^.+\\(.+)$", "$1")); GUI will be updated at next iteration
EndFunc

Func _WriteConfig()
    $sLocalUser = GUICtrlRead($guiLocalUSER)
    $sLocalPwd = _StringEncrypt(1, GUICtrlRead($guiLocalPWD), $EncryptionKey, 1)
    $sDomainUser = GUICtrlRead($guiDomainUSER)
    $sDomainPwd = _StringEncrypt(1, GUICtrlRead($guiDomainPWD), $EncryptionKey, 1)
    $sDomain = GUICtrlRead($guiDomain)
    $sDomainOU = GUICtrlRead($guiDomainOU)


    $sExcludeUser = GUICtrlRead($guiExcluded)

    $sPreMigrate = GUICtrlRead($guipremigrate)
    $sPostMigrate = GUICtrlRead($guipostmigrate)

    IniWrite ($INI_File, "Actions", "PreMigrate", $sPreMigrate)
    IniWrite ($INI_File, "Actions", "PostMigrate", $sPostMigrate)

    IniWrite ($INI_File, "Local", "Username", $sLocalUser)
    IniWrite ($INI_File, "Local", "Password", $sLocalPwd)

    IniWrite ($INI_File, "Domain", "Domain", $sDomain)
    IniWrite ($INI_File, "Domain", "DomainOU", $sDomainOU)
    IniWrite ($INI_File, "Domain", "Username", $sDomainUser)
    IniWrite ($INI_File, "Domain", "Password", $sDomainPwd)

    GUIDelete($GUI)
    Exit
EndFunc

Func _CleanUpUserProfiles()
    Local $iStart = 0, $sVal
    Local $sReg = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
    While 1
        $iStart += 1
        $sKey = RegEnumKey($sReg, $iStart)
        If @Error Then ExitLoop
        If StringMid($sKey, 7, 2) <> 21 Then ContinueLoop
        $sVal = RegRead($sReg & "\" & $sKey, "ProfileImagePath")
;~      MsgBox(0, "DEBUG", $sVal)
        $sUserProfile = StringRegExpReplace($sVal, "^.+\\(.+)$", "$1")
        If $sUserProfile <> @UserName Then $sRefCount=RegRead($sReg & "\" & $sKey, "RefCount")
        If $sRefCount <> 0 Then $sResetRefCount=RegWrite($sReg & "\" & $sKey, "RefCount", "REG_DWORD", 0)
        If @error <> 0 AND @error <> 1 Then MsgBox(16, $App, "An error has occurred while attempting to reset a user profile." & @CRLF & @CRLF & "User Profile: " & $sUserProfile & @CRLF & "Error Code: " & @error)
    WEnd
    _JoinDomain()
EndFunc   ;==>_CleanUpUserProfiles

Func _JoinDomain()

    Local $PreMigrate = IniRead($INI_File, "Actions", "PreMigrate", "")

    Local $LocalUSER = IniRead($INI_File, "Local", "Username", "")
    Local $LocalPWD = _StringEncrypt(0, IniRead($INI_File, "Local", "Password", ""), $EncryptionKey, 1)

    Local $setDomainOU
    Local $Domain = IniRead($INI_File, "Domain", "Domain", "")
    Local $DomainOU = IniRead($INI_File, "Domain", "DomainOU", "")
    Local $DomainUSER = IniRead($INI_File, "Domain", "Username", "")
    Local $DomainPWD = _StringEncrypt(0, IniRead($INI_File, "Domain", "Password", ""), $EncryptionKey, 1)

    If $DomainOU <> "" Then $setDomainOU = " /OU:"  ; Sets the Domain OU of where to add a computer account if specified within the ini file.

    RunWait(@Comspec & " /c netdom.exe join " & @ComputerName & " /Domain:" & $Domain & $setDomainOU & $DomainOU & " /UserD:" & $DomainUSER & " /PasswordD:" & $DomainPWD & " > C:\UPMT.log", @ScriptDir, @SW_MINIMIZE) ; Joins workstations to domain and assigns it to correct OU
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce", "UPMT", "REG_SZ", """" & @ScriptFullPath & """ /MIGRATE") ; Adds registry entry to RunOnce part of registry to start User Profile migration after reboot
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "AutoAdminLogon", "REG_SZ", 1) ; Sets AutoAdminLogon within registry
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultUserName", "REG_SZ", $LocalUSER) ; Sets DefaultUserName within registry
    RegWrite("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultPassword", "REG_SZ", $LocalPWD) ; Sets DefaultPassword within registry

    If $PreMigrate <> "" Then RunWait("regedit -s " & $PreMigrate, @ScriptDir)

    If (MsgBox(33, $App & " - Reboot Required", "Your computer has just joined to the " & $Domain & " domain." & @CRLF & @CRLF & "On next reboot, all user profiles (your settings) will be migrated which may take some time." & @CRLF & @CRLF & "Press OK to reboot now, or Cancel to return to Windows." & @CRLF & "If you click Cancel, please reboot over lunch or as you leave this evening.") = 1) Then
        Shutdown(22)  ;Force or force if hung a reboot
    EndIf
EndFunc

Func _MigrateProfiles()

    Local $profileCount = 1 ; Sets $ProfileCount variable
    Local $percent_value = 0 ; Sets $Percent_Value variable
    Local $ProfileAgeLimit = IniRead($INI_File, "Actions", "ProfileAgeLimit", "") ; Reads ProfileAgeLimit from ini file
    Local $PostMigrate = IniRead($INI_File, "Actions", "PostMigrate", "") ; Reads Post Migration Registry File name from ini file
    Local $Domain = IniRead($INI_File, "Domain", "Domain", "") ; Reads Domain Name from ini file
    $Domain = StringLeft($Domain, (StringInStr($Domain, ".")-1))
    If $Domain <> "" Then
        $Domain = $Domain & "\"
    Else
        Msgbox(16, $App, "The domain has not been specified or is not fully qualified." & @CRLF & @CRLF & "Please run " & @ScriptName & " /CONFIG and make the necessary changes.")
        Exit
    EndIf

    Local $ExcludeUserList = IniReadSection($INI_File, "ExcludeUsers") ; Reads a list of excluded users specified within the ini file

    RegDelete("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "AutoAdminLogon") ; Removes AutoAdminLogon within registry
    RegDelete("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\WinLogon", "DefaultPassword") ; Removes DefaultPassword within registry

    If $PostMigrate <> "" Then RunWait("regedit -s " & $PostMigrate, @ScriptDir) ; Imports registry file if specified within ini file

    Local $iStart = 0, $sVal
    Local $sReg = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" ; Location within the registry to read
    While 1
        $iStart += 1
        $sKey = RegEnumKey($sReg, $iStart)
        If @Error Then ExitLoop
        If StringMid($sKey, 7, 2) <> 21 Then ContinueLoop
        $sVal = RegRead($sReg & "\" & $sKey, "ProfileImagePath") ; Obtains profile path from registry key
        $UserProfileList = StringRegExpReplace($sVal, "^.+\\(.+)$", "$1") ; Regular expression to remove full path and obtain username
        _ArrayAdd($IncludeUser,$UserProfileList) ; Adds value to Array

    WEnd

    _ArrayDelete($IncludeUser, 0) ; Deletes Array

    For $i = 1 to $ExcludeUserList [0][0]
        $UserProfileList = _ArraySearch($IncludeUser, $ExcludeUserList[$i][1]) ; Searching the array for a match
        if $UserProfileList <> -1 then _ArrayDelete($IncludeUser, $UserProfileList) ; If a match is found delete the entry
    Next

    $GUI = GUICreate($App, 600, 250, -1, -1, BitOR($WS_CAPTION, $WS_POPUP, $WS_BORDER, $WS_CLIPSIBLINGS), $WS_EX_WINDOWEDGE) ; Creates GUI Window
    GUISetFont(12, 800, 2, "Arial") ; Sets Font to size 2 and BOLD
    $Label1 = GUICtrlCreateLabel("Please Wait...", 10, 10, 580, 20) ; Creates Label 1
    GUISetFont(8.5, 400, 0, "Arial") ; Sets Font to default
    $Label2 = GUICtrlCreateLabel($message, 10, 30, 580, 190) ; Creates Label 2
    $Progress = GUICtrlCreateProgress(10, 210, 580, 15, $PBS_SMOOTH) ; Creates Progress Bar
    GUICtrlSetColor($Progress, 0xff0000) ; Sets Progress Bar Colour
    $Label3 = GUICtrlCreateLabel("Migrating User Profile: <OBTAINING DATA>", 10, 230, 580, 20) ; Creates Label 3
    GUISetState() ; Set GUI State

    For $r = 0 to UBound($IncludeUser)-1
        $percent_value = ($profileCount / UBound($IncludeUser)) *100 ; Calculates Percentage
        GUICtrlSetData($Label3, "Migrating User Profile: " & $IncludeUser[$r] & " (" & $profileCount & " of " & UBound($IncludeUser) & ")") ; Updates Label with data from variables
        GUICtrlSetData($Progress, $percent_value) ; Sets Progress Bar percentage
        $sUser = $IncludeUser[$r] ; Assigns value of array to variable

        $ProfileDate =  FileGetTime("C:\Documents and Settings\" & $sUser & "\NTUSER.DAT", 0) ; Gets Modification Time
        If Not @error Then
            $ProfileModificationTime = $ProfileDate[0] & "/" & $ProfileDate[1] & "/" & $ProfileDate[2] ; Converts date into date format YYYYMMDD
            $ProfileAge = _DateDiff( 'D',$ProfileModificationTime,_NowCalc()) ; Calculates the number of days since the profile was last modified
            If $ProfileAge <= $ProfileAgeLimit AND $ProfileAgeLimit <> "" Then RunWait(@Comspec & " /c moveuser.exe " & $sUser & " " & $Domain & $sUser & " >> C:\UPMT.log", @ScriptDir, @SW_MINIMIZE) ; Command used if Profile Age Limit is specified within ini file
            If $sUser <> "Administrator" Then RunWait(@Comspec & " /c net localgroup ""Administrators"" " & $sUser & " /delete >> C:\UPMT.log", @ScriptDir, @SW_MINIMIZE) ; If user is not Administrator then removes Local / Domain User from Local Administrators Group
            RunWait(@Comspec & " /c net localgroup ""Power Users"" " & $sUser & " /delete >> C:\UPMT.log", @ScriptDir, @SW_MINIMIZE) ; Removes Local / Domain User from Local Power Users Group
            RunWait(@Comspec & " /c net localgroup ""Users"" " & $Domain & $sUser & " /delete >> C:\UPMT.log", @ScriptDir, @SW_MINIMIZE) ; Removes Domain User from Local Users Group
        EndIf
        $profileCount +=1 ; Increments $profileCount by 1
    Next

    Shutdown(22)  ;Force or force if hung a reboot
    Sleep(10000) ; Pauses script for 10 seconds
EndFunc

Func _Quit()
    GUIDelete($GUI) ; Deletes GUI Window(s)
    Exit ; Exits Script
EndFunc

Exit

pleasant tool update

Words of Wisdom and Favourite Quotes:

'Nothing is impossible, despite what other people say and think, prove them wrong and show them what you can do!'

'Understanding is a three edged sword, your side, their side and the truth!'

'The truth that humanity has never been able to grasp, is that death may be the only absolute freedom there is!'

'I've run out of places to put the brush... what do you suggest?'

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...