Jump to content

Moving User Files to a New Computer Automatically


Go to solution Solved by ViciousXUSMC,

Recommended Posts

I had an idea for a script that I wanted to see if anybody else has attempted with a good degree of success or perhaps has a better way of doing it.

I often need to replace/upgrade a computer that has 30+ user profiles on the old machine.

The "best practice" is to install the new machine and wait a week or so until everybody has logged on to create their profile on the new machine and then copy over their personal files.

This can be a big task when managing so many computers and users, so I am thinking of making a script that will check the current user profile name, and if it exists as one of my old profile names with data, do the file transfer to copy the user files from the old user profile that I will have saved somewhere on the disk.

I would just put a copy of all the old profile data on the drive along with the script and let it do its thing.  My concern is mostly that the script would fire off right as somebody is logging in the first time and if they do not give the computer enough time to transfer all the files it would probably "break" the script as I would most likely write it in a way that after it has transferred a copy of the files it would write a flag as to not do a transfer again.

I have in the past sometimes used Windows Easy Transfer, this lets me move the files before they log into the computer for the first time but it has been removed from Windows 8.1.  You still have the Windows User State Migration Tool but it is way more complicated to use, and normally I would not want to transfer over certain settings like appdata/registry because if they got any virus/corruption I do not want to carry it to the new computer.  I would also need to wait for the scan to capture all the data, and then again for it to push it back out.  So I think my raw file transfer idea may be ideal for my needs given it works properly.

So any vote up or down as to if this should/would work or better ways to go about it?

__________________________

Idea in more depth 

On Root of C will be the old Users folder Named Old User Data and it will have a self compiled Autoit script as an .exe that I will point to with a shortcut in the all users startup folder.

I think it would be wise to add a delay to the start of the script so it does not fire off while windows may be doing some first time setup in the background so say a 2 minute delay with Sleep() at that time, it would also be wise to either do a SplashText or MsgBox to notify the user that a file transfer has started and not to log off or shut down the computer until it has finished.

As for the actual file transfer part I would use the @UserName to query the current user and see if that same profile name exists in the Old User Data folder.  If it does start the file copy and give the above copy message, if not exit.

For the file transfer part, it would be a file copy and when it has finsihed needs to notify the user that the file copy has finished, but it also needs to perform an action so that it will not run again next time they log in.  I was thinking "writing a flag" by simply creating a txt file that says "user has transfered" or something to the old files directory and have an if statement that if this file exists the copy does not happen and exit.  However I think simply renaming the old profile to "userprofilename copies" would also work well as then it would fail the "if this name exists" check from before and make it visually faster/easier to see if that user has logged in and started the file transfer.

Most of this script should be pretty easy, and I should be able to do it with my skill level.  I am sure that you guys could make a way more advanced solution but thats the idea in a nutshell. 

Link to comment
Share on other sites

Once the script runs and starts, you could pop up some GUI labeled like "Your previous personal files are being copied, please don't turn off the machine."

Then again, what is the worst that could happen that interrupts your copying script if it runs in the background? No user would possibly shut down his computer right after he started it up.

For the copying itself, I'd suggest you only take files that are not part of a fresh created standard windows profile. Pics, Documents, every custom created folder, maybe some configuration from the AppData folder.

There's a pretty mighty copying tool around called robocopy. Google that.

As for the "run once per user" I'd suggest putting something like this in the all users autostart.

If RegRead("HKEY_CURRENT_USER\Software\MyProfileCopy", "FilesCreated") = 1 Then Exit
RegWrite("HKEY_CURRENT_USER\Software\MyProfileCopy", "FilesCreated", "REG_SZ", 1)
 
;Script goes here
Link to comment
Share on other sites

Just getting started, already hit a problem.  DirCopy is not working right for me. 

I have some msgbox to make sure my paths are correct and they are, the behavior is that say I put a file in 

C:Old User FilesProfiletext.txt 

That file will move

But if I have a file at C:Older User FilesProfileDesktoptext.txt

It does not seem to move the files (not merging desktop folders) I think I had an issue with DirCopy before a long time ago and I forget if I fixed it or had ot resort to XCopy instead.

Just the beginning script: (And I have tried with #RequireAdmin)

$OldDataSrc = "C:\Old User Data\"


;sleep to let windows fully boot
Sleep(100)

If FileExists($OldDataSrc & @UserName) Then
    SplashTextOn("Black Magic Automation", "Transfering your old user files to the new computer, do not turn off the computer until completed!", -1, 200, -1, -1, 18)
    MsgBox(0, "Debug If Profile Exists", "Profile " & @UserName & " Exsits and transfer starting")
    DirCopy($OldDataSrc & @UserName, @UserProfileDir, 1)
    MsgBox(0, "", "Copying " & $OldDataSrc & @UserName & " to " & @UserProfileDir)
Else
    MsgBox(0, "Debug If Profile Exists", "Profile " & @UserName & " Does Not Exsits and Exiting")
    Exit
EndIf
Edited by ViciousXUSMC
Link to comment
Share on other sites

 

Once the script runs and starts, you could pop up some GUI labeled like "Your previous personal files are being copied, please don't turn off the machine."

Then again, what is the worst that could happen that interrupts your copying script if it runs in the background? No user would possibly shut down his computer right after he started it up.

For the copying itself, I'd suggest you only take files that are not part of a fresh created standard windows profile. Pics, Documents, every custom created folder, maybe some configuration from the AppData folder.

There's a pretty mighty copying tool around called robocopy. Google that.

As for the "run once per user" I'd suggest putting something like this in the all users autostart.

If RegRead("HKEY_CURRENT_USER\Software\MyProfileCopy", "FilesCreated") = 1 Then Exit
RegWrite("HKEY_CURRENT_USER\Software\MyProfileCopy", "FilesCreated", "REG_SZ", 1)
 
;Script goes here

 

Yeah one issue I combat working with sensitive data is that the users are not admin and so they cant do a regwrite, and embeding a runas is not really "secure" and credentials can change without notice.  That is why I like to use the rename or create a file solution so that they do not need admin rights (given its a user accessible location)

For the what files to transfer, that is easy if I get DirCopy working I will manually prune the data out of the archive before I leave to save disk space and so that I can just copy everything in the user profile folder without worring about being selective.  Pretty much anything can go other than the AppData folder I will delete that, and I may delete some desktop shortcuts (and I may have a seperate part of the script that will do that for me)

As for my DirCopy issue.  I verified if I change my destination to say C:TestingFolder that it is moving the desktop folder and all its contents so the issue is that it is not merging with the desktop folder in the C:usersprofile location.

Edited by ViciousXUSMC
Link to comment
Share on other sites

Of course they can. Most programs the users run need to save their settings and rarely use .ini files.

The HKEY_CURRENT_USER part of the registry can always be written by the logged on user, no matter if he's an admin or not.

As for picking the files the user might want to keep: how about copying the folder on their desktop, marking it as "(old)" and simply informing the user that this is their old stuff and they can take what they still need?

Edited by Radiance
Link to comment
Share on other sites

Messed with Robocopy for a while, didn't work out so well lol its hard to get Macros and Varibles in a CMD without some sort of errors.

But I did figure out a "fix" for DirCopy.  Instead of trying to push the entire UserProfile Directory if I choose a sub folder say Desktop or MyDocuments those will copy and merge properly.  This is ultimately what I needed to do anyways so its not a bad fix.

I am still tidying everything up but its looking good so far.

$OldDataSrc = "C:\Old User Data\"


;sleep to let windows fully boot
Sleep(20000)

If FileExists($OldDataSrc & @UserName) Then
    SplashTextOn("Black Magic Automation", "Transfering your old user files to the new computer, do not turn off the computer until completed!", -1, 200, -1, -1, 18)
    ;MsgBox(0, "Debug If Profile Exists", "Profile " & @UserName & " Exsits and transfer starting")
    DirCopy($OldDataSrc & @UserName & "\Desktop", @UserProfileDir & "\Desktop", 1)
    DirCopy($OldDataSrc & @UserName & "\Contacts", @UserProfileDir & "\Contacts", 1)
    DirCopy($OldDataSrc & @UserName & "\Downloads", @UserProfileDir & "\Downloads", 1)
    DirCopy($OldDataSrc & @UserName & "\Favorites", @UserProfileDir & "\Favorites", 1)
    DirCopy($OldDataSrc & @UserName & "\Links", @UserProfileDir & "\Links", 1)
    DirCopy($OldDataSrc & @UserName & "\My Documents", @UserProfileDir & "\My Documents", 1)
    DirCopy($OldDataSrc & @UserName & "\My Music", @UserProfileDir & "\My Music", 1)
    DirCopy($OldDataSrc & @UserName & "\My Pictures", @UserProfileDir & "\My Pictures", 1)
    DirCopy($OldDataSrc & @UserName & "\My Videos", @UserProfileDir & "\My Videos", 1)
    DirMove($OldDataSrc & @UserName, $OldDataSrc & @UserName & " Copied "  & @MON & "-" & @MDAY & "-" & StringTrimLeft(@YEAR, 2), 9)
    SplashOff()
    MsgBox(0, "Black Magic Automation", "Your Old Files Have been Moved to your New Profile, You can now Shutdown the computer safely and continue work")
Else
    ;MsgBox(0, "Debug If Profile Exists", "Profile " & @UserName & " Does Not Exsits and Exiting")
    Exit
EndIf
Link to comment
Share on other sites

  • Solution

Ok finalized and ready for production testing.  Works good in my test environment, very happy with it.

The Installer Script for an Admin to run off a flash drive or share:

#RequireAdmin

DirCreate("C:\Old User Data\")
FileInstall("C:\My Places\Scripting\AutoIT\My Scripts\Automove User Data\AutoDataTransfer.exe", "C:\Old User Data\AutoDataTransfer.exe", 1)
FileCreateShortcut("C:\Old User Data\AutoDataTransfer.exe", @StartupCommonDir & "\AutoDataTransfer.exe", "C:\Old User Data", "", "", "", "", "0", "1")
MsgBox(0, "Black Magic Automation", "Done! - Please put the old user profiles in the C:\Old User Data Folder")

The File Copy Script that runs at startup

$OldDataSrc = "C:\Old User Data\"


;sleep to let windows fully boot
Sleep(20000)

If FileExists($OldDataSrc & @UserName) Then
    SplashTextOn("Black Magic Automation", "Transfering your old user files to the new computer, do not turn off the computer until completed!", -1, 150, -1, -1, 18)
    ;MsgBox(0, "Debug If Profile Exists", "Profile " & @UserName & " Exsits and transfer starting")
    DirCopy($OldDataSrc & @UserName & "\Desktop", @UserProfileDir & "\Desktop", 1)
    DirCopy($OldDataSrc & @UserName & "\Contacts", @UserProfileDir & "\Contacts", 1)
    DirCopy($OldDataSrc & @UserName & "\Downloads", @UserProfileDir & "\Downloads", 1)
    DirCopy($OldDataSrc & @UserName & "\Favorites", @UserProfileDir & "\Favorites", 1)
    DirCopy($OldDataSrc & @UserName & "\Links", @UserProfileDir & "\Links", 1)
    DirCopy($OldDataSrc & @UserName & "\My Documents", @UserProfileDir & "\My Documents", 1)
    DirCopy($OldDataSrc & @UserName & "\My Music", @UserProfileDir & "\My Music", 1)
    DirCopy($OldDataSrc & @UserName & "\My Pictures", @UserProfileDir & "\My Pictures", 1)
    DirCopy($OldDataSrc & @UserName & "\My Videos", @UserProfileDir & "\My Videos", 1)
    DirMove($OldDataSrc & @UserName, $OldDataSrc & @UserName & " Copied "  & @MON & "-" & @MDAY & "-" & StringTrimLeft(@YEAR, 2), 9)
    SplashOff()
    MsgBox(0, "Black Magic Automation", "Your Old Files Have been Moved to your New Profile, You can now Shutdown the computer safely or continue to work")
Else
    ;MsgBox(0, "Debug If Profile Exists", "Profile " & @UserName & " Does Not Exsits and Exiting")
    Exit
EndIf
Link to comment
Share on other sites

I do a lot of backup and restores in the shop but with home user machines.

Often the problem is people dont store there stuff in the correct places, the amount of times i see picture or music folders on the root is unreal.

So whilst this approach works for a business scenario just be aware it would miss other files if it was a home user who thinks he know better

As for robocopy look in my sig for an easy version, ive done thousands of backups now with robocopy and i would trust it over any other method

Alternate copy params with logfile if you need it

If $Os = "V-" Then
        $sCopyParams = '/COPY:D /S /ZB /XJD /XJF /R:0 /W:0 /V /LOG:C:\Backup\Logfile.txt /XA:SHT' ; XP Params /NJS removed for the log
    Else
        $sCopyParams = '/COPY:D /S /ZB /XJD /XJF /R:0 /W:0 /V /MT:16 /LOG:C:\Backup\Logfile.txt /XA:SHT' ; Vista + Params /NJS removed for the log
    EndIf

Another way is like this if i didnt need includes and excludes but wanted a progress

_CopyFolder(@UserProfileDir & "\Pictures", $sDestination & '\Pictures')

Func _CopyFolder($sSourceFolder, $sDestFolder)
    Local $ipct
    DirRemove($sDestFolder, 1)
    Local $iSourceSize = DirGetSize($sSourceFolder), $iDestSize
    Local $pid = Run(@AutoItExe & ' /AutoIt3ExecuteLine "DirCopy(''' & $sSourceFolder & ''', ''' & $sDestFolder & ''')"')
    Do
        GUICtrlSetData($hLabel3, "Checking " & StringReplace($sSourceFolder, @UserProfileDir & "\", ""))
        $iDestSize = DirGetSize($sDestFolder)
        $ipct = $iDestSize / $iSourceSize) * 100
        GUICtrlSetData($hProgress, $ipct)
        GUICtrlSetData($hLabel4, $ipct & ' Percent Complete')
        Sleep(20)
    Until Not ProcessExists($pid)
EndFunc   ;==>_CopyFolder

Also can you not back them all at once when you make the backups? this may work for you

Func _UserList() ;BrewmanNH origanal author
    Local $UserList, $aUserList, $X, $aUserList[10], $UserList[10]
    If $sDataCheck = 'V+' Then
        $UserList = _FileListToArray($sSource & 'Users', "*.*", 2)
        For $I = 1 To $UserList[0]
            Select
                Case $UserList[$I] = "All Users"
                Case $UserList[$I] = "Default"
                Case $UserList[$I] = "Default User"
                Case $UserList[$I] = "Public"
                Case Else
                    $aUserList[$X] = $UserList[$I]
                    $X += 1
                    If $X >= UBound($aUserList) Then
                        ReDim $aUserList[UBound($aUserList) + 10]
                    EndIf
            EndSelect
        Next
        ReDim $aUserList[$X]
    ElseIf $sDataCheck = 'V-' Then
        $UserList = _FileListToArray($sSource & 'Documents and Settings', "*.*", 2)
        For $I = 1 To $UserList[0]
            Select
                Case $UserList[$I] = "All Users"
                Case $UserList[$I] = "Default User"
                Case $UserList[$I] = "NetworkService"
                Case $UserList[$I] = "LocalService"
                Case $UserList[$I] = "Administrator"
                Case Else
                    $aUserList[$X] = $UserList[$I]
                    $X += 1
                    If $X >= UBound($aUserList) Then
                        ReDim $aUserList[UBound($aUserList) + 10]
                    EndIf
            EndSelect
        Next
        ReDim $aUserList[$X]
    EndIf
    _ArrayDisplay($aUserList)
    ;$sUserList = _ArrayToString($aUserList, "|")
    Return $aUserList
EndFunc   ;==>_UserList
Edited by Chimaera
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...