Oct 242017

NOTE: This only works between like profile versions. eg. You can’t migrate your 2008R2 profiles to Server 2016 and expect it to work. See this chart.
I moved from UPM to FSLogix earlier this year, and decided to write my own powershell script to convert the UPM profiles to .vhd. FSLogix has its own conversion process (which I didn’t find a whole lot of info on), but I decided to create my own.
What this script does:
- Gets a list of all UPM profile directories in the root path (that you supply) and displays them to you to select which one(s) you would like to convert via out-gridview
- For each profile you select:
- Gets the username from the profile path – you will have to edit this part for your environment… explanation in the script
- Use the username to get the SID (FSLogix profiles use the username and sid to name the profile folder)
- Creates the FSLogix profile folder (if it doesn’t exist)
- Sets the user as the owner of that folder, and gives them full control
- Creates the .vhd (my default is 30GB dynamic – edit on line 70 if you wish to change it) – if it doesn’t exist (if it does skip 7, 9-10)
- Attaches the .vhd
- Creates a partition and formats it ntfs
- Assigns the letter T to that drive (edit on line 73 if you wish to change that)
- Creates the T:\Profile directory
- Grants System/Administrators and the user full control of the profile directory
- Copies the profile from the UPM path to the T:\Profile directory with /E /Purge – if you are re-running this script on a particular profile it will overwrite everything fresh
- Creates T:\Profile\AppData\Local\FSLogix if it doesnt exist
- Creates T:\Profile\AppData\Local\FSLogix\ProfileData.reg if it doesn’t exist (this feeds the profilelist key at logon)
Hi David,
I´m trying to migrate some UPM profiles to FSLogix profiles with your script but I cannot get further. I´ve edit the $newprofilepath and $oldprofile variable as needed for our environment, but I do not get any respsone from the script. Actually nothing happens. In general I just want to ask you for help.
Regards
Martin
Martin there is more to it than just changing the $newprofilepath and the $oldprofiles variables. Read through the commented sections.
[…] some research I choose to try out a script created by David Ott. You can check the original post here, or on the FSLogix […]
[…] Citrix UPM Profiles to FSLogix Profiles Conversion Powershell Script […]
How does the User profile know which disk to attached. Could you please clarify.
$sid = (New-Object System.Security.Principal.NTAccount($sam)).translate([System.Security.Principal.SecurityIdentifier]).Value
reports:
New-Object : Ausnahme beim Aufrufen von “.ctor” mit 1 Argument(en): “Die Zeichenfolge kann keine Länge von 0 (null)
haben.
Parametername: name”
In C:\batch\Migrate.ps1:43 Zeichen:9
+ $sid = (New-Object System.Security.Principal.NTAccount($sam)).transla …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [New-Object], MethodInvocationException
+ FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
Any Ideas? I´m stucked at the moment and can´t find the error.
Without this $sid I get a profile-folder called “_” and a “Profile.vhd”
Is it possible to create VHDX instea of VHD?
Thanks a lot
Marc
#########################################################################################
# Setup Parameter first here newprofile oldprofile subfolder1 subfolder2
# Requires -RunAsAdministrator
# My Userprofiles come only with SAMAccount Name without Domain "\Username\2012R2\UPM_Profile
#########################################################################################
# Example from my UPM Path "\\path_to_your_share\username\2012R2\UPM_Profile"
# fslogix Root profile path
$newprofilepath = "\\path_to_your_share\FSLogix"
# UPM Root profile path
$oldprofilepath = "\\path_to_your_share\UPM\Userprofiles"
# Subfolder 1 - First Path to UPM_Profile Folder in UPM Profiles - see my example above
$subfolder1 = "2012R2"
# Subfolder 2 - First Path to UPM_Profile Folder in UPM Profiles - see my example above
$subfolder2 = "UPM_Profile"
#########################################################################################
# Do not edit here
#########################################################################################
$oldprofiles = gci $oldprofilepath | select -Expand fullname | sort | out-gridview -OutputMode Multiple -title "Select profile(s) to convert"| %{
Join-Path $_ $subfolder1\$subfolder2
}
foreach ($old in $oldprofiles) {
$sam = Split-Path ($old -split $subfolder1)[0] -leaf
$sid = (New-Object System.Security.Principal.NTAccount($sam)).translate([System.Security.Principal.SecurityIdentifier]).Value
$regtext = "Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$sid]
"ProfileImagePath
"="C:\\Users\\$sam
""FSL_OriginalProfileImagePath
"="C:\\Users\\$sam
""Flags
"=dword:00000000"State
"=dword:00000000"ProfileLoadTimeLow
"=dword:00000000"ProfileLoadTimeHigh
"=dword:00000000"RefCount
"=dword:00000000"RunLogonScriptSync
"=dword:00000000"
$nfolder = join-path $newprofilepath ($sam+"\"+$sid+"_"+$sam)
if (!(test-path $nfolder)) {New-Item -Path $nfolder -ItemType directory | Out-Null}
& icacls $nfolder /setowner "$env:userdomain\$sam" /T /C
& icacls $nfolder /grant $env:userdomain\$sam
:
(OI)
(CI)F /T
$vhd = Join-Path $nfolder ("Profile_"+$sam+".vhdx")
$script1 = "create vdisk file="$vhd
" maximum 30720 type=expandable"
"$vhd$script2 = "sel vdisk file=
"
rnattach vdisk"
"$vhd$script3 = "sel vdisk file=
"
rncreate part prim
rnselect part 1
rnformat fs=ntfs quick"
"$vhd$script4 = "sel vdisk file=
"
rnsel part 1
rnassign letter=T"
"$vhd$script5 = "sel vdisk file
"
rndetach vdisk"
"$vhd$script6 = "sel vdisk file=
"
rnattach vdisk readonly
"r
ncompact vdisk"if (!(test-path $vhd)) {
$script1 | diskpart
$script2 | diskpart
Start-Sleep -s 5
$script3 | diskpart
$script4 | diskpart
& label T: Profile-$sam
New-Item -Path T:\Profile -ItemType directory | Out-Null
start-process icacls "T:\Profile /setowner SYSTEM"
Start-Process icacls -ArgumentList "T:\Profile /inheritance:r"
$cmd1 = "T:\Profile /grant $env:userdomain\$sam
:
(OI)
(CI)F"
:Start-Process icacls -ArgumentList "T:\Profile /grant SYSTEM
(OI
)(CI
)F"Start-Process icacls -ArgumentList "T:\Profile /grant Administrators
:
(OI)
(CI`)F"Start-Process icacls -ArgumentList $cmd1
} else {
$script2 | diskpart
Start-Sleep -s 5
$script4 | diskpart
}
"Copying $old to $vhd"
& robocopy $old T:\Profile /E /Purge /r:0 | Out-Null
if (!(Test-Path "T:\Profile\AppData\Local\FSLogix")) {
New-Item -Path "T:\Profile\AppData\Local\FSLogix" -ItemType directory | Out-Null
}
if (!(Test-Path "T:\Profile\AppData\Local\FSLogix\ProfileData.reg")) {$regtext | Out-File "T:\Profile\AppData\Local\FSLogix\ProfileData.reg" -Encoding ascii}
$script5 | diskpart
}
Thank you so much. Your script worked. However, when I run the script, the end result is “Profile_Username.vhdx”. is there a way i can modify the script so that end result is “Username.vhdx”? without the “Profile_”?
Thanks
You could, but why? FSLogix needs the Profile_ to work..
[…] UPM to Profile Container […]
[…] UPM nach Profile Container […]
The script works fine, except at the permissions files/ownership.
On Windows, the ownership of the users folder are Administrators, after that, it is the user for subfolders+files.
With FSLogix, is it SYSTEM not administrators, the same thing, the user is owner.
With the original script, the owner is the group administrators, not the user. I had errors on loading ntuser.dat, folder desktop,etc.
I moved the line about Removing the inheritance (T:\profile), looks it breaks some permissions while copying, the logic we should add permissions before removing ?
Robocopy copy attributes don’t work well (/DATO, /DATSOU, etc.) on my testings, I wanted to copy the owner attribute, but i had some strange permissions added (user LogonsessionID).
After the robocopy, I added a line to make the user full owner with the command /T, and then I change T:\profile’s owner as system.
Also adding the user permissions after copying the files with /T to be recursive, sometimes, the user wasn’t included in the permissions (?)
I modified a bit the script and it works now, it respects the permissions for the profile. It might look not optimized, but 100% covered. I don’t want to get support calls for profile users that failed on migration.
$cmd1 = “T:\Profile /grant ${env:userdomain}\${sam}:(OI)(CI)F /T”
$cmd2 = “T:\Profile /setowner ${env:userdomain}\${sam} /T”
Start-Process icacls -ArgumentList “T:\Profile /grant SYSTEM:(OI)(CI)F”
Start-Process icacls -ArgumentList “T:\Profile /grant Administrateurs:(OI)(CI)F”
Start-Process icacls -ArgumentList “T:\Profile /inheritance:r”
} else {
# if the vhd does exist then attach, wait 5 seconds, assign letter T
$script2 | diskpart
Start-Sleep -s 5
$script4 | diskpart
}
# copies in the UPM profile to the Profile directory on the vhd /E /Purge – this is so it will update with the latest info
“Copying $old to $vhd”
& robocopy $old T:\Profile /E /Purge /r:0 | Out-Null
Start-Process icacls -ArgumentList $cmd1
start-process icacls -ArgumentList $cmd2
start-process icacls “T:\Profile /setowner SYSTEM”
Hoping to get some quick help with the modifications to the script you made for migrating UPM to VHD.
Where exactly do you insert the lines that you adjusted?
Hi
Please help me to fill this bit because my folder path do not have sub folders.
My old UPD path: \\PNI-UPD-001\UPD
New fslogix UPD path: \\UPD-2019-T01\Profiles
So
# Example from my UPM Path “\\path_to_your_share\username\2012R2\UPM_Profile” ???
# fslogix Root profile path
$newprofilepath = “\\UPD-2019-T01\Profiles”
# UPM Root profile path
$oldprofilepath = “\\PNI-UPD-001\UPD”
# Subfolder 1 – First Path to UPM_Profile Folder in UPM Profiles – see my example above
$subfolder1 = “2012R2” ???
# Subfolder 2 – First Path to UPM_Profile Folder in UPM Profiles – see my example above
$subfolder2 = “UPM_Profile” ???
Thank you.
Dash
Nice Blog man, Very nice!!
there is any way to migrate citrix UPM profile to Local Profile .
Sure, just set the profiles not to delete at logoff, then disable UPM.
Hello, I was able to run the script successfully and the profile.vhdx file got created,no issues here, thank you. But when the FSLogix agent access it during login, it names the file as CORRUPT_###_Profile_upi, then it creates a new profile_sid and then deletes the corrupt file. Not sure where I am getting it wrong or something else is wrong here. Please help.
Jump into the IRC channel for some help. join.citrixirc.com.
Thank you Ryan; I was able to fix it. The issue was that the script was copying only the AppData folder from the UPM folder and leaving the rest being, once I tweak the script to copy all data from UPM, the FSLogix Agent recognized the vhdx file and build further on that. Then I was able to see my desktop, icons and bookmarks.
what changes where made to copy everything?
Thanks for sharing!
I modified the script, to convert our V6-Roaming profiles to FSLogix-VHDX profiles. Everything works as expected, except for the users start menu. It is completely empty, adding any items is not possible either.
We use a GPO to deploy a customized Start menu to users, which works fine for V6-Profiles. It also works if I first login the user once on the new server (so that the .vhdx is created automatically) and then run the modified script for copying the users data. This is not an option due to the amount of users and the time it would take converting them all one by one.
Any suggestions on how to fix the start menu when using the script to create the vhdx-file?
Nico, unfortunately, the script owner retired. I’m not sure how this could be fixed. I’d check out WorldofEUC and ask around in there.
Hi, the script is not available on the link. Could you please re share it?