One drawback of the User State Migration Tool (USMT) is that it needs to run locally on the source and destination machines to migrate user state data. Luckily, with PowerShell we can easily create a function to migrate data between two remote machines.

USMT has been a staple for system administrators for years and has greatly reduced the time to migrate data between computers. USMT has the ability to migrate user files, OS settings, and application settings. It can even do this between different Windows operating system versions. For instance, you can use USMT to migrate data between Windows 7 and Windows 10.

For a bit more detail about using USMT, you can take a look at Timothy Warner's article Windows 8 migration - User data and settings. While the most current version of USMT supports Windows 10, the method of using USMT in this article is still relevant. Although you can use USMT along with the Microsoft Deployment Toolkit (MDT), some administrators may choose to use it as a standalone tool to migrate data between two machines.

How USMT works ^

The two main executables used with USMT are scanstate.exe and loadstate.exe, executed from the command line. Scanstate.exe scans the source computer for user data and application settings. For instance, you can configure your migration .xml files to copy settings for Office and Google Chrome among other applications. After scanning, it backs up the data to a .mig file on a Server Message Block (SMB) share. I will not go into detail about how to configure your .xml files because there are many references online.

After backing up the source computer, you run loadstate.exe on the destination computer from the command line. This then takes that same .mig file and restores the data. The greatest benefit of USMT is that a user included in the migration will log in to the destination computer and see many of the same application settings, such as Chrome browsing history and Outlook profile.

Invoke-USMT function overview ^

Before I explain my Invoke-USMT function, I will point out that this is not a Microsoft-supported solution and may not work in all environments. The function requires PowerShell remoting, along with the Credential Security Support Provider protocol (CredSSP) to transfer the migration data to and from a network share.

To use the function, you must have the Windows Assessment and Deployment Kit (ADK) supported by the OS you want to migrate and an SMB share available to store the migration data. You also need to have local administrator privileges on both remote machines.

Here is an overview of what the function does:

  • Uses Test-Connection to ensure it can ping both source and destination computers.
  • Copies the USMT files from a specified location to the source and destination computers.
  • Enables CredSSP on the computer running the function and both remote computers.
  • Uses Invoke-Command with CredSSP authentication to perform scanstate on the source computer. Creates a .mig file that stores the migration data on the SMB share. Note that it copies the $SecureKey secure string variable to each machine for use in the /key.  The string is encrypted throughout the process.
  • Uses Invoke-Command and CredSSP authentication to migrate the data from the .mig file to the destination computer.
  • Removes the USMT files from source and destination computers.
  • Disables CredSSP on the local and remote computers.

Invoke-USMT example ^

In this scenario, I have a source and destination machine both joined to my domain. I want to migrate a specific domain user's (Dan's) profile and other data from the source machine to the destination machine remotely from my computer.

From PowerShell I run Invoke-USMT specifying the source/destination computer, username I want to migrate, share path for storing the migration files, USMTFilePath for copying the USMT files to the source/destination computers, and the domain name. After running this, it prompts me for the secure key used to encrypt the data included in the .mig file.

Subscribe to 4sysops newsletter!

Using Invoke USMT

Using Invoke USMT

Invoke-USMT function code ^

function Invoke-USMT {
        [Parameter(Mandatory=$true, HelpMessage='Enter USMT key')]
        #Test source and destination computers are online
        if (!(Test-Connection -ComputerName $SourceComputer -Count 2))
            Write-Warning -Message "Count not ping $SourceComputer"
         if (!(Test-Connection -ComputerName $DestinationComputer -Count 2))
            Write-Warning -Message "Count not ping $DestinationComputer"
        #Copy USMT files to remote computers
            Copy-Item -Path $USMTFilesPath -Destination "\\$SourceComputer\C$\" -ErrorAction Stop -Recurse -force -con
            Copy-Item -Path $USMTFilesPath -Destination "\\$DestinationComputer\C$\" -ErrorAction Stop -Recurse -force
            Write-Error $_
        #Enable CredSSP
        Invoke-Command -ComputerName $SourceComputer -Credential $Credential -ScriptBlock {Enable-WSManCredSSP -Role server -Force} 
        Invoke-Command -ComputerName $DestinationComputer -Credential $Credential -ScriptBlock {Enable-WSManCredSSP -Role server -Force} 
        Enable-WSManCredSSP -Role client -DelegateComputer $SourceComputer -Force
        Enable-WSManCredSSP -Role client -DelegateComputer $DestinationComputer -Force 
        #Start startscan on source
        Invoke-Command -ComputerName $SourceComputer -Authentication Credssp -Credential $Credential -Scriptblock {
            $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Using:SecureKey)
            $Key = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
            c:\USMTFiles\scanstate.exe "$Using:SharePath\$Using:Username" /i:c:\usmtfiles\printers.xml /i:c:\usmtfiles\custom.xml /i:c:\usmtfiles\migdocs.xml /i:c:\usmtfiles\migapp.xml /v:13 /ui:$Using:Domain\$Using:UserName /c /localonly /encrypt /key:$Key /listfiles:c:\usmtfiles\listfiles.txt /ue:pcadmin /ue:$Using:Domain\*
        } -ArgumentList {$UserName,$SharePath,$SecureKey,$SourceComputer,$Domain}
        #Start loadscan on destination
        Invoke-Command -ComputerName $DestinationComputer -Authentication Credssp -Credential $Credential -Scriptblock {
            $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Using:SecureKey)
            $Key = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
            c:\USMTFiles\loadstate.exe "$Using:SharePath\$Using:Username" /i:c:\usmtfiles\printers.xml /i:c:\usmtfiles\custom.xml /i:c:\usmtfiles\migdocs.xml /i:c:\usmtfiles\migapp.xml /v:13 /ui:$Using:Domain\$Using:username /c /decrypt /key:$Key
        } -ArgumentList {$UserName,$SharePath,$SecureKey,$DestinationComputer,$Domain}

        #Remove USMT files on remote computers
        Remove-Item \\$SourceComputer\C$\USMTFiles -Force -Recurse
        Remove-Item \\$DestinationComputer\C$\USMTFiles -Force -Recurse

        #Disable CredSSP on remote computers
        Invoke-Command -ComputerName $SourceComputer -Credential $Credential -ScriptBlock {Disable-WSManCredSSP -Role server }
        Invoke-Command -ComputerName $DestinationComputer -Credential $Credential -ScriptBlock {Disable-WSManCredSSP -Role server }  
        Disable-WSManCredSSP -Role client        
1 Comment
  1. Robert 2 years ago

    Excellent script.  This helped me understand so much.  Thank you for putting this out here.


    There is an error in your scanstate call.  The script is calling the config file with a /i:  which causes scanstate to fail.  This should be /config:

    So the command should be the following

     Invoke-Command -ComputerName $SourceComputer -Authentication Credssp -Credential $Credential -Scriptblock {
                $BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Using:SecureKey)
                $Key = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
                c:\USMTFiles\scanstate.exe "$Using:SharePath\$Using:Username" /i:c:\usmtfiles\printers.xml /config:c:\usmtfiles\custom.xml /i:c:\usmtfiles\migdocs.xml /i:c:\usmtfiles\migapp.xml /v:13 /ui:$Using:Domain\$Using:UserName /c /localonly /encrypt /key:$Key /listfiles:c:\usmtfiles\listfiles.txt /ue:pcadmin /ue:$Using:Domain\*
            } -ArgumentList {$UserName,$SharePath,$SecureKey,$SourceComputer,$Domain}


Leave a reply

Please enclose code in pre tags

Your email address will not be published. Required fields are marked *


© 4sysops 2006 - 2021


Please ask IT administration questions in the forums. Any other messages are welcome.


Log in with your credentials


Forgot your details?

Create Account