Try the following script, which backs up Desktop, Documents, Downloads, Pictures, Music, Videos, Favorites and selected AppData\Roaming data. It excludes NTUSER.DAT, NTUSER.*.LOG*, and other profile registry files. The user's new Windows profile can have a different local profile/SID, and copying files such as NTUSER.DAT or the entire AppData tree can corrupt the new profile.
param(
[Parameter(Mandatory = $true)]
[string]$Username,
[Parameter(Mandatory = $true)]
[string]$BackupRoot
)
$SourceProfile = "C:\Users\$Username"
$BackupProfile = Join-Path $BackupRoot $Username
if (-not (Test-Path $SourceProfile)) {
Write-Host "Profile not found: $SourceProfile" -ForegroundColor Red
exit 1
}
New-Item -Path $BackupProfile -ItemType Directory -Force | Out-Null
$LogFile = Join-Path $BackupProfile "ProfileBackup.log"
function Copy-ProfileData {
param(
[string]$Source,
[string]$Destination
)
if (-not (Test-Path $Source)) {
Add-Content $LogFile "SOURCE NOT FOUND: $Source"
return
}
New-Item -Path $Destination -ItemType Directory -Force | Out-Null
Add-Content $LogFile ""
Add-Content $LogFile "Copying: $Source"
Add-Content $LogFile "To: $Destination"
robocopy $Source $Destination /E /COPY:DAT /DCOPY:DAT /R:2 /W:2 /XJ `
/XD "AppData\Local\Temp" `
/XF "NTUSER.DAT" "NTUSER.DAT.LOG1" "NTUSER.DAT.LOG2" `
"NTUSER.INI" "ntuser.dat.LOG*" `
/LOG+:$LogFile /TEE
if ($LASTEXITCODE -ge 8) {
Add-Content $LogFile "RESULT: FAILED - Robocopy exit code $LASTEXITCODE"
}
else {
Add-Content $LogFile "RESULT: SUCCESS - Robocopy exit code $LASTEXITCODE"
}
}
# Standard user folders
$Folders = @(
"Desktop",
"Documents",
"Downloads",
"Pictures",
"Music",
"Videos",
"Favorites"
)
foreach ($Folder in $Folders) {
Copy-ProfileData `
-Source (Join-Path $SourceProfile $Folder) `
-Destination (Join-Path $BackupProfile $Folder)
}
# Selected roaming application settings
$RoamingSource = Join-Path $SourceProfile "AppData\Roaming"
$RoamingBackup = Join-Path $BackupProfile "AppData\Roaming"
if (Test-Path $RoamingSource) {
Copy-ProfileData `
-Source $RoamingSource `
-Destination $RoamingBackup
}
# Optional: back up selected Local application data.
# Do not copy the entire AppData\Local because it contains
# caches, temporary files and machine-specific application data.
$LocalAppData = Join-Path $SourceProfile "AppData\Local"
$LocalBackup = Join-Path $BackupProfile "AppData\Local"
$LocalFolders = @(
"Microsoft\Edge\User Data",
"Google\Chrome\User Data"
)
foreach ($Folder in $LocalFolders) {
Copy-ProfileData `
-Source (Join-Path $LocalAppData $Folder) `
-Destination (Join-Path $LocalBackup $Folder)
}
# Export a list of installed applications for reference
$InstalledAppsFile = Join-Path $BackupProfile "InstalledApplications.txt"
Get-ItemProperty `
"HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" ,
"HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*" ,
"HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*" `
-ErrorAction SilentlyContinue |
Where-Object { $_.DisplayName } |
Sort-Object DisplayName |
Select-Object DisplayName, DisplayVersion, Publisher |
Format-Table -AutoSize |
Out-String |
Set-Content $InstalledAppsFile
Write-Host ""
Write-Host "Profile backup completed." -ForegroundColor Green
Write-Host "Backup location: $BackupProfile"
Write-Host "Log: $LogFile"
For the backup location, you might want to use a network share or external storage rather than another location under the user's existing profile. For example:
\\FileServer\UserMigration$\username
Run it as an administrator:
.\Backup-UserProfile.ps1 -Username jsmith -BackupRoot "\\FileServer\UserMigration$"
On the replacement PC, first join it to Entra ID/hybrid AD as appropriate and have the user sign in once so Windows creates the new profile. Then the data can be copied from the backup into the newly created profile.
If the above response helps answer your question, remember to "Accept Answer" so that others in the community facing similar issues can easily find the solution. Your contribution is highly appreciated.
hth
Marcin