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:

  1. 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
  2. For each profile you select:
    1. Gets the username from the profile path – you will have to edit this part for your environment… explanation in the script
    2. Use the username to get the SID (FSLogix profiles use the username and sid to name the profile folder)
    3. Creates the FSLogix profile folder (if it doesn’t exist)
    4. Sets the user as the owner of that folder, and gives them full control
    5. 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)
    6. Attaches the .vhd
    7. Creates a partition and formats it ntfs
    8. Assigns the letter T to that drive (edit on line 73 if you wish to change that)
    9. Creates the T:\Profile directory
    10. Grants System/Administrators and the user full control of the profile directory
    11. 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
    12. Creates T:\Profile\AppData\Local\FSLogix if it doesnt exist
    13. Creates T:\Profile\AppData\Local\FSLogix\ProfileData.reg if it doesn’t exist (this feeds the profilelist key at logon)

Here is the script!

Dec 052016


Using Citrix Profile Management with profile streaming enabled should keep your logon times pretty low.  Recently, they updated the version of our Antivirus (Trend Micro) to the latest, and suddenly I started seeing desktops fail with “session prepare failure” errors.  After much investigation it had something to do with the behavior monitoring feature of the AV software hanging Citrix Profile Management long enough to cause the desktop to freeze/unregister.  Turning off the profile streaming option fixed that issue.

Since then I have noticed logon times have skyrocketed.  I used to see an average logon time of about 30 seconds, and after disabling profile streaming I see average times well over 1 minute (some individuals as high as 5 minutes).

In order to try to get our logon times back down to a reasonable time I wrote a script to investigate the profile store.  I found a few folders which contain a ton of files – files that have to be copied in at each logon slowing things down.

The Fix

I wrote a blog post a while back about using a Powershell Script to redirect folders via symbolic links.  You can find that here http://www.citrixirc.com/?p=315.   We can use that same method to redirect “bad” folders, but using Citrix Workspace Environment Management instead (no need to learn how to script!).  NOTE: Users must have the “Create symbolic links” right!


Of course, you are going to need WEM setup in your environment.  Carl Stalhood has a great step by step on how to set it up here http://www.carlstalhood.com/workspace-environment-manager/.

A couple of caveats I would add to his blog post:
If you are installing on a PVS image before shutting down your maintenance/private mode vdisk to re-seal, kill the Norskale Agent Host Service.  For whatever reason if you don’t do this it can cause your vms in standard mode to take an obscenely long time to shutdown.
If you have a PVS environment and you have redirected the WEM cache to the persistent drive use a startup task to refresh the cache, force restart the Norskale Agent Host Service, and start netlogon after.  If the cache doesn’t already exist WEM doesn’t seem to check with the WEM server.  You have to create the cache, and then restart the service so that it reads it, and force restarting the Norskale Agent Host Service will stop netlogon (dependent on it).  Chicken or the egg thing…

Assuming you have WEM setup and running:

Create a Folders and Files action that creates the redirected folder structure in the user home directory or where ever you want to put it.  In the \\server\share\VDIPaths (or whatever you name it) have the folder structure laid out for all the folders you wish to redirect (empty folders) – this is your folder “template” directory:
ie: \\server\share\VDIPaths\Recent

The source path is the folder you just created and the target is where you want to put it.  Make sure overwrite target if existing and run once are unchecked

Under Options – Copy Directory Content (creates the folder structure in the user’s %homeshare% folder or where ever you put it), and make sure the Execution order is “0” – happens first.

Next we need to perform 3 tasks for each folder you want to redirect to the user %homeshare%\VDIPaths folder (or where ever you decide to put it)

We will first move the existing data in the profile to the redirect location, second delete the existing data in the profile, and finally create the symbolic link.


The first thing we do is create the move operation.  Name it whatever you want.  The source is the local profile path to the user, and the target is where we want to move the files

Under the Options Tab select Move Directory Content and set the execution order to 1.  We want the “VDIPaths\Recent” folder to have been created already by the create task


Set the source path to the directory you want to delete

Under the Options Tab select Delete Files / Folders and set the Execution order to 2 as we want the files to be moved to the new location prior to deleting.

Create the Symbolic Link

The Source will be the %homeshare% location, and the target will be the local profile path location.

Under the Options tab set the action to Create Directory Symbolic Link and set the execution order to 3.

Assign tasks

Assuming you have already setup configured users you can now assign the 4 tasks above to your test user or group.  Going forward you will only need to create the latter 3 tasks, and just make sure you update the “template” directory accordingly.

Assign the first task (create VDI_Paths in my case) setting always true
Assign the second task (Move Recent in my case) setting always true
Assign the third task (Delete Recent in my case) setting always true
Assign the 4th task (Recent_Symbolic_Link in my case) setting always true

0 – Create VDI_Paths – copies the folder structure to the user’s %homeshare% directory
1 – Move Recent – moves the contents of %appdata%\Microsoft\Windows\Recent to %homeshare%\VDIPaths\Recent
2 – Delete Recent – deletes the %appdata%\Microsoft\Windows\Recent folder
3 – Recent_Symbolic_Link – Creates a symbolic link at %appdata%\Microsoft\Windows\Recent pointing to %homeshare%\VDIPaths\Recent

You end up with something that looks like this:

If you click into the Recent symbolic link you will see it still looks like it is on the local C: drive as far as the path goes, but it is “redirected” to the path you specified.  If it does not work check the Norskale Vuem Agent.log file in the user profile, and look for the error.  If it is a permissions issue, then you probably have to allow the user to create symbolic links via gpo and/or local policy (I put it both places just to be sure it takes).

I have done this for the following paths thus far with success

%appdata%\Microsoft\Windows\Recent – all the recent places/docs a user has opened
%appdata%\Microsoft\Signatures – Outlook signatures
%localappdata%\Apps\2.0 – This one is for clickonce apps – I also had to make another task to create the “Apps” folder in the local profile in case it doesn’t exist (only one that is different from the rest)
%localappdata%\Microsoft\Internet Explorer\DOMStore – some IE cache that gets quite large
%appdata%\Microsoft\Office\Recent – all recent Office docs
%localappdata%\Google – Chrome cache
%appdata%\Mozilla – Firefox cache
%localappdata%\Mozilla – Firefox cache
%localappdata%\Apps\Evernote – Evernote (unfortunately some of my users need this)
%localappdata%\WebEx – WebEx Cache

Once you are certain all of the existing data for each of your users has been moved to their %homeshare% directory (or where ever you put it) you can exclude those folders from UPM, and remove the Move/Delete tasks.  It won’t hurt to leave them though…

May 062016

If you have tried to use Windows 10 in XenDesktop with Citrix Profile Management you have probably run into two major issues.

The Issues
The first issue is the start menu… which is now a database located at %localappdata%\TileDataLayer\Database.  At logoff when profile manager tries to copy it off it can’t due to services locking the files.  This results in the user logging on and their start menu not working.

The second issue revolves around SMB2/3.  SMB1 would close files as soon as it was done with them, but 2/3 leave them open for a little longer in case they are requested again.  This means when a user logs off and their Pooled Random desktop shuts down file locks can remain in the profile store if the shutdown process happens too fast (which it does 99% of the time).  Basically, if a user was to logoff and then try to log back on in a short period of time their logon would be greatly delayed due to the “ghost” file locks.

The Workarounds
Start Menu – This one is a bit tricky.  When a user logs off we need to stop the Tile Data model server and State Repository Service (in that order) so that profile manager can copy the start menu database off to the user store.  Here is the rub… a normal user cannot stop these services, so you can’t use a logoff script!  Here is what you do… logon as a local administrator and…

  1. Create a powershell script on the root of C:\ – name it logoff.ps1
    1. Open powershell_ise.exe as administrator and write these 2 lines in the white space at the top (if no white space hit the new button to create a new script).
      stop-service tiledatamodelsvc -force
      stop-service staterepository -force
    2. Save it as C:\logoff.ps1 (or put it where ever you want – just remember where it is)
  2. Right click the start menu – hit run – type in taskschd.msc and hit ok
  3. Right click the Task Scheduler Library node and select Create Basic Task…
  4. Name it whatever you want – I named mine logoff – hit next
  5. Select “When a specific event is logged” on the next screen and hit next
  6. Under Log: start typing “Sec”  the Security log should show up
  7. Under Source type in “Microsoft Windows security auditing” (no quotes)
  8. Event ID will be 4647 – hit next
  9. leave Start a program selected – hit next
  10. in the program/script blank C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
  11. in the add arguments blank “-executionpolicy unrestricted -file c:\logoff.ps1” (no quotes) – if you put the script somewhere else make sure you have the path correct.
  12. click next, and on the next screen check the box “Open the Properties dialog…” and hit Finish
  13. Click Change User or Group, type in “system” (no quotes) and hit ok
  14. Check “Run with highest privileges”, and hit ok

Now when a user initiates a logoff the system will stop the Tile Data model server and State Repository Service.  This will allow profile manager to copy off the start menu database.

Ghost File locks
This one is pretty easy – we just delay the shutdown with a shutdown script.  This allows the file locks to be released at shutdown.  Here is what you do… (you should still be logged on as a local administrator)

  1. Run powershell_ise.exe as administrator and type these 2 lines in the white space at the top… again if no white space hit the new button.
    stop-service brokeragent -force
    start-sleep -s 30
  2. Save it as C:\shutdown.ps1 (or where ever you want)
  3. Right click the start menu – hit run – type in gpedit.msc
  4. Under “Computer Configuration\Windows Settings\Scripts” double click on Shutdown
  5. Click the PowerShell Scripts tab
  6. Click Add – browse to the script you just created – hit ok
  7. Hit Ok again on the shutdown properties box, and close the local group policy editor

At shutdown this script will kill the brokeragent service (just in case delaying the shutdown would allow the desktop to appear “available” again), and delay the shutdown by 30 seconds.  This allows all file locks in the profile manager store to be released.

Bonus – UPM policy settings for Windows 10 (These are mine, so you may need to tweak for your environment – of course redirect all you can)

Exclusion list (registry) 
Software\Microsoft\Internet Explorer\Recovery

Exclusion list – directories
AppData\Local\Microsoft\Windows Live
AppData\Local\Microsoft\Windows Live Contacts
AppData\Local\Microsoft\Terminal Server Client
AppData\Local\Windows Live
AppData\Local\Google\Chrome\User Data\Default\Cache
AppData\Local\Microsoft\Windows\Temporary Internet Files
AppData\Roaming\Citrix\PNAgent\Icon Cache
AppData\Roaming\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys
AppData\Roaming\Macromedia\Flash Player\#SharedObjects
AppData\Local\Microsoft\Internet Explorer\Recovery
AppData\Local\Microsoft\Windows Mail
AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Dropbox
AppData\Local\Downloaded Installations
AppData\Local\Cisco\Unified Communications\Jabber\CSF\Voicemail
AppData\Local\Cisco\Unified Communications\Jabber\Voicemail
AppData\Local\ATT Connect
AppData\Local\Cisco\Unified Communications\Jabber\Crash Dump
AppData\Local\Cisco\Unified Communications\Jabber\CSF\Logs
AppData\Roaming\Microsoft\Internet Explorer\UserData
AppData\Local\Microsoft\Windows\Application Shortcuts
AppData\Local\Microsoft\Group Policy
AppData\Local\Microsoft\Media Player

Exclusion list – files

Files to synchronize

Directories to synchronize

Folders to mirror

Process Internet Cookie files on logoff  – Enabled

Process logons of local administrators – Enabled

Profile streaming – Enabled

Path to user store – \\server\share\%username%.%userdomain%\!CTX_PROFILEVER!!CTX_OSBITNESS!

Enable Profile management – Enabled

One more bonus!!
Based mostly on this Citrix blog – Windows 10 Optimization for XenDesktop – I wrote a powershell script to automatically optimize your Windows 10 gold PVS image… available HERE.

Nov 242015

Have you ever excluded a directory after the fact, and realized that Citrix Profile Manager does not remove the directory from the store? Have you noticed “AppData\Local\Microsoft\Internet Explorer\DOMStore” or “AppData\Roaming\Microsoft\Windows\Recent” filling up with tons of small files/empty folders – most of which are old as dirt (delaying logon)? Have you pulled out your hair over the tons of junk OICE folders showing up in AppData? I have a solution for all of this mess… I wrote another script!

What you need:

Powershell of course – minimum v2 I think
An account which has rights to go through all of the profiles and delete the junk files/folders (run the script as that user if it isn’t you).
A .csv file with your exclusion/sync list (read the CSV portion in the comments of the script – muy importante!)

Here is the script


Dec 192014

Like the title says this is for a very specific use case which I have run into, so definitely not for everyone.


The company I work for plans on switching the user home directories to a DFS path in order to accommodate our cloud DR solution. We currently redirect folders via Citrix policies in XenDesktop to the user home directories (ie: \\server\path\username). This path is to change to the DFS path as well, so when a user logs onto the cloud Desktop as a Service (DaaS) desktop their folders are redirected like normal. The new path will be \\domain\dfspath\userpath\username, but it is really the same place as before (2 different paths pointing to the same place). If you change the Citrix policy to redirect the folders to \\domain\dfspath\userpath from \\server\path it will copy the contents of the old path to the new (which really does nothing because it is already there), BUT then it will delete it from the old path (since the “old” and “new” path are really the same the redirected folders are deleted)!!! Using good ol’ Microsoft redirection policies you can set the policy to not move data, but with Citrix policies I don’t see this option.

Basically, if I switch the policy to point the redirected folders to the new DFS path, a user logs on, and all their redirected folders go *POOF*. In our environment that’s pretty much everything but AppData.

I screwed around with the registry a bit and found if you delete the values under HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders and User Shell Folders that point to the share along with the History key under HKCU:\Software\Citrix\UserProfileManager\FolderRedirection, the folders are redirected fine after the DFS path is in place with no problems.


The Script

My choices after finding the work around were to:

  1. Go the easy route – Delete all the current profiles
    1. Obviously that won’t fly
  2. Load each NTUSER.DAT file into the registry one at a time and edit them
    1. With so many profiles that would take forever
    2. Would need a very long window as I couldn’t have users logging on/off hosing my work and their redirected folders
  3. Get a window to disable logons to our XD environment, get everyone logged off, and use a script to load every ntuser.dat file/edit/unload
    1. Only need a short window

I chose option 3 and got to work on a script below. Read the comments between the <# #> marks!  As always test test test…

Your best bet is to copy the script below into your favorite powershell editor it doesn’t format very nicely here… I just use powershell_ise.exe



$start = Get-Date <# Get the start time to calculate how long the script took at the end #>
<# we get the folders under the root of the profile store (full names), for each append the path to where the NTUSER.DAT would be found, and save that as the $profiles variable. THIS WILL ALMOST CERTAINLY BE DIFFERENT FOR YOU, SO FIGURE OUT YOUR PATH #>
$profiles = gci \\server\profiles | ?{$_.psiscontainer -eq $true} |select -expand fullname | sort | %{Join-Path $_ "v2x64\UPM_Profile\NTUSER.DAT"}
<# This is where the fun starts. If you want to test this against a single test user profile comment out the $profile variable above with a pound sign before it, and make a new line like this: $profiles = "\\server\profiles\testuser\upm_profile\ntuser.dat" #>
foreach ($profile in $profiles) {
<# We check to see if the NTUSER.DAT file exists... if not it continues on to the next profile in the list #>
if ((Test-Path $profile) -eq $false) {continue}
<# This checks for completed jobs and outputs the messages to the screen (job starts in a sec). Then removes the completed job #>
if ((Get-Job -State Completed).count -gt 0) {
$jobs = Get-Job -State Completed
$jobs | Receive-Job
$jobs | Remove-Job
<# This sets the max running jobs to 10 - adjust this at your own risk - ie: if you change the 10 to 100 it will load 100 NTUSER.DAT files into the registry at a time ... that could be bad resource wise #>
while ((Get-Job -State Running).count -ge 10) {
Start-Sleep -s 1
<# The hive variable below is important... this is the name the NTUSER.DAT hive will get in HKLM. YOU WILL HAVE TO PLAY WITH THIS SO YOU GET IT RIGHT IN YOUR ENVIRONMENT. in my case it will name the hive username_temp - ie: user1_temp if the username is user1 #>
$hive = (($profile -split ".domain") -split "\\")[2] + "_temp"
<# Here we start the job - jobs run a separate instance of powershell, so it will load multiple hives. In this case there will be 10 hives loaded into the registry at a time (DO NOT OPEN REGEDIT WHILE THIS SCRIPT IS RUNNING... IT WILL STOP THE HIVES FROM UNLOADING) #>
Start-Job -name $hive {param($profile,$hive)
<# Here we start reg.exe with arguments to load the user hive, and saves the process info as $load.  Then it checks the exitcode so it can tell you if it loaded
or not#>
$load = start-process -passthru -filepath reg.exe -argumentlist "load HKLM\$hive $profile" -Wait -WindowStyle Hidden
if ($load.ExitCode -ne "0") {
Write-Host "$profile could not be loaded" -f Red
} else {
Write-Host "$profile loaded"
<# $change variable comes into play in a sec... default is 0 #>
$change = "0"
<# Here we set the location to the registry path where the shell folders and user shell folders keys live #>
Set-Location hklm:\$hive\Software\Microsoft\windows\CurrentVersion\Explorer
<# We search for any key which has *shell* in the name (shell folders and user shell folders).  Then we get the key path of those keys, and all the properties
under those keys, and look for any values that are pointing to the server where the current share is hosted.  Once we have those we remove the property, and set
$change to 1... indicating that the shell folders were modified#>
gci .\ | ?{($_.psiscontainer -eq $true) -and ($_.name -like "*shell*")} | %{
$regpath = $_.pspath
$properties = $_.property
foreach ($property in $properties) {
$val = (Get-ItemProperty $regpath).$property
<# edit your server name here  #>
if ($val -like "*server*") {
$change = "1"
Remove-ItemProperty -Path $regpath -Name $property
<# If $change is 1 then we remove the folder redirection "history" key under the Citrix path #>
if ($change -eq "1") {
Set-Location HKLM:\$hive\Software\Citrix\UserProfileManager\FolderRedirection
if ((Test-Path .\History) -eq $true) {
ri .\History -Recurse -Force
<# We pop-location to leave the registry paths, do some cleanup so that we can unload the hive cleanly, and attempt to unload it.  If it fails it will try up
to 5 times to unload the hive.  And will let you know after the job runs #>
gci env: | Out-Null
gci variable: | Out-Null
$att = 0
while ((Test-Path HKLM:\$hive) -and ($att -le 5)) {
$unload = start-process -PassThru -FilePath reg.exe -ArgumentList "unload HKLM\$hive" -Wait -WindowStyle Hidden
$att += 1
if ($unload.ExitCode -ne "0") {
Write-Host "Unable to unload $profile" -f Red
} else {
Write-Host "$profile successfully unloaded"
<# This cleans up the NTUSER.LOG files that get created when the hive is loaded #>
gci (Split-Path $profile -Parent) -Force | ?{($_.psiscontainer -eq $false) -and ($_.Name -like "ntuser*") -and ($_.name -ne "ntuser.dat") -and ($_.name -ne "ntuser.ini") -and ($_.Name -ne "ntuser.pol")} | ri -Force
} -ArgumentList $profile,$hive | Out-Null
Get-Job | Wait-Job | Receive-Job
Get-Job | Remove-Job
$end = Get-Date
$minutes = ($end - $start).Minutes
$seconds = ($end - $start).Seconds
Write-Host "Total run time $minutes minutes $seconds seconds."

Sep 182014

I recently ran into an issue where Citrix Profile Manager was not catching all the files from a user installed Office Add-in. I found the path to the files and they were in %localappdata%\Apps\2.0. Even if I specifically added a policy to sync that folder it still did not get every file needed for the Add-in to work. After banging my head against the wall trying to get profile manager to handle it I decided to write a logoff script to “backup” that folder to the user’s home share at logoff, and a logon script to “restore” it at logon. That worked, but it delayed logon/logoff as those files were copied to/from the user profile.

On top of that issue, I also had the need to redirect Chrome and Firefox cache directories to user home shares as they were soon to be installed on our VDI image. Of course, you can do both without the script you are about to see (GPO in the case of Chrome, and an .ini file with Firefox). I just figured kill three birds with one stone.

The answer ended up being very simple. Junction points! For those of you who may not know a junction point (aka reparse point or symbolic link) is basically a shortcut that Windows treats as a folder. A normal shortcut to “\\server\share\path” on your desktop would show that path in the address bar if you clicked on it. A symbolic link would show C:\Users\<username>\Desktop\<name of the link>. This allows you to basically “redirect” a specific folder. For those of you who have a “crappy app” that points its data to %userprofile%\AppData\<path> instead of %AppData% and prevents you from redirecting AppData this may help you as well.

Now all I need is a logon script (powershell) to create these junction points.

Requirements for this script:
1. Users must have the “Create symbolic links” right (set in GPO)

2. Users must have a Home Folder (if they don’t you could simply rewrite the script to create a folder somewhere using $env:username in the path).

Detailed explanation of what this script does:
1. Sets the location to C:\ so when it calls cmd it won’t complain about the path (assuming the script is going to run from a network share)

2. Imports a .csv file with the information
This .csv file has headers “localpath”, “homepath”, and “LorR”
localpath = the folder within local or roaming appdata. If the path is down inside somewhere make sure you include the whole path. In my case I want to get %localappdata%\Apps\2.0, so the localpath would be “Apps\2.0”
homepath = the path in the users home directory where you want the files located. Same as localpath you don’t include the entire share path… just the path you want it to create inside the share.
LorR = local or roam – so the script knows where to put the junction points.

3. For each line in the .csv file calls a function that will:
a. Decide if the path is in local or roaming appdata (LorR)
b. Create the folder structure on the user’s home folder
c. Checks if the local folder already exists. If so, checks to see if it is already a junction (which it shouldn’t be). If the path is *2.0 (path to the Office Add-ins) it moves those files to the home folder, and creates the junction. If it is anything else it deletes the folder (would be user installed chrome/firefox cache directories), and creates the junction.

After running this at logon my user now shows this in %appdata%

If I open Mozilla it shows to be local, but it is actually pointing to my home folder


The only “issue” I have seen thus far is Chrome will warn that the cache is on a network share the first time it is launched.

Below is the powershell script. Feel free to edit it to fit your needs, and make sure you test thoroughly before implementing into any production environment.


Feb 182013

Profile Optimization and “How do I speed up login times?” generally go hand-in-hand. These have to be two of the most important and most talked about items when it comes to delivering XenApp desktops. There are lot of different philosophies and strategies with regards to this, and in this article I’ll simply talk about what I have implemented in my environment. I have gone through extensive testing, tracing, logging, and analyzing of my settings and will show you what has worked for me. You can use some of these techniques to troubleshoot your own environment and see if you can get some gain in yours.

To start, I have leveraged many whitepapers, blogs, and Citrix KBs to generate my settings. I’d like to give credit where credit is due. First the Citrix XenApp and XenDesktop Policy Planning Guide was a good resource and baseline for everything. Second, this Citrix blog about Citrix Profile Management had a lot of great information. Also, CitrixIRC, of course, has been a great reference to talk things through with a bunch of great Citrix Admins. Join our chat at http://join.citrixirc.com. I have also read many other things on these topics, but I don’t recall them well enough to cite them.

Let’s get the framework in perspective here. I work for a Citrix CSP (Citrix Service Provider) and we currently have a couple dozen farms mostly in the SMB space (<250 users) I don’t do any enterprise work, so my tools and tricks are built around an SMB mindset. I use Citrix Profile Manager and GPOs, exclusively. I do not use any other third party tools to manage my profiles. I try to keep my environments simple enough for our other admins to be able to manage them. I think that if you can configure and test these tools properly they can do the job well enough to not need additional cost factors in our environments.

That being said lets start with Folder Redirection! Simply put, I redirect everything, except for AppData, utilizing GPOs. I manipulate AppData with UPM and we will talk about that later. Redirecting everything keeps it out of the profile and keeps the profile small. Simple enough.

Folder redirection isn’t the only culprit for large profiles. There are other commonly used programs that keep crap in the profile. I use GPOs to redirect these items as well. Outlook PST and OST files. Download the Office admx templates and USE THEM. “Microsoft Outlook 2010/Miscellaneous/PST Settings”. I set “Default location for PST/OST files” to a network drive. Well, I’m not using cached mode you say? Other things are stored in PST files as well, such as SharePoint Lists, so keep this in mind. AutoArchive? This will create a PST also, so if you are using this, you will want to make sure PST/OST files are moved. AutoRecover files are also stored in the profile. You can redirect Excel and Word Autorecover using the same admx templates.

How about Evernote? A lot of my users use Evernote, and by default the database is stored in AppData\Roaming. I redirect this to a network drive with a GPP Registry key. “HCU\Software\Evernote\Evernote” REG_SZ “DatabasePath”. I have seen very large databases and this is a good tweak to keep the profiles small.

Let’s talk AppData. First, I use UPM to exclude AppData\Local and AppData\LocalLow at the root. I keep AppData\Roaming in the users profile mainly for the performance implications of this being redirected on a large scale. However, I use the UPM to exclude a bunch of directories to keep it as small as possible. I will attach my UPM GPO for you to look at these settings in more depth. I exclude about 12 directories from AppData\Roaming that were gathered from the various best practices documents. Using Chrome? Chrome keeps all of its settings in AppData\Local. Shame on you, Google! With UPM, this is no problem. I do 2 things with Chrome. First, I include AppData\Local\Google in Synchronization. Second, I exclude AppData\Local\Google\Chrome\User Data\Default\Cache, Cached Theme Images, and JumpListIcons. This allows my users’ Chrome settings to save, but excludes the not-needed bloat directories.

Don’t forget the cookies! I have written another blog here on that. Read it!

How about the rest of the UPM settings? Again, I’m going to attach my UPM policy in here somewhere, but we can run through the basic settings. I delete cached copies of local profiles. We always want to load a fresh profile each time. This will lower profile corruptions. How about profile streaming and active writeback? Well, I turn these off. Most people will say that’s dumb, and those are great features, and you should keep those on. Well, I can see how these are great features, but again, I’m tuning these settings for my environments. With the tweaks I am implementing I have an average profile size of 30meg. The profile itself can load in less than 1 second on a gigabit network, so I’m not too concerned about this. These settings are nice for larger setups, but in my environment I’ll keep it as simple as possible.

Did you use the 2008 R2 Optimization Guide for XenApp 6/6.5? Well, don’t forget this blog post about one of the settings you need to change if you are using the UPM. Without changing it, UPM times out a lot and slows logon/logoff processing.

Don’t forget to exclude all of the un-needed folders inside of the profile as well. This is done with a GPO.

When all is said and done, here is what my profile looks like. Of course, this is a test user, but this is a great foundation to build user profiles on. Notice there are not any folders in there except for Windows and AppData.

Do you already have an environment built and would like to tweak these settings? I certainly did. I actually wrote a script that would go through the Profile Store and delete out all of the bloat from the users’ existing profiles. You can check that out script here. Its powershell, so have fun. I had users with 1gig profiles and was able to lower then to 30-60meg in our internal environment. Note, this must be run from the Profile Store directory.

One setting that works for me, but will require testing, is the GPO to wait for network at computer startup and logon. I was able to gain about 13 seconds on my logon times when I disabled this setting. Your mileage may vary.

Are you using GPPs for shortcuts and printers and such? I did a lot of GPP tracing to analyze these mappings and found this to be true inside my environments. If you create GPP Shortcuts using “update” it takes about 200ms for each item at each logon to parse. If you have 60 shortcuts between the start menu and desktop, that’s 12 seconds right there. That’s not a short amount of time. Setting these to “create” will speed this up to about 5ms per item at each login. You can change it to “update” if you actually want to change something in the future. I gained another 15 seconds on my logins when I changed all of my GPP shortcuts to “create”. The same basic numbers apply for printers too, however, I have not traced them to get exact numbers yet.

Login times have a lot to do with how many GPOs that you have in your environment. Remember these tips. Always prefer fewer larger GPOs opposed to many smaller ones. Each GPO has a set base processing time that can be avoided by consolidating GPOs into one larger one. Make sure you disable Computer/User settings in a GPO if you aren’t using them. This lowers login time a second or so per GPO.

So, what did I use to troubleshoot all of these things? I do curse Microsoft for getting rid of the userenv.log detailed logging. Nothing works quite as good. UPM logging is a really good place to start, however. You can turn it on in the UPM Policy GPO, and parse the logs with the UPM Log Parser. You should also be using the GPSvc.log. You can set that up using this blog. Don’t forget to create the “usermode” directory if it doesn’t exist, or the logs won’t work. You can also turn on GPP Tracing in a GPO under “Computer Configuration\Policies\Administrative Templates\System\Group Policy\Logging and Tracing”. You can turn all of these on, and enable tracing, to get detailed information of your GPPs. Some people like to use Policy Reporter to go through the logs. This is a nice tool, but I just read the logs manually.

Using all of these tips and tricks above, I was able to get my test user in my test environment to log in after about 9 seconds on the 3rd login. Obviously the first 2 logins are a tad slower as it builds the profile from scratch and runs some other scripts that I have in my environment. Now, keep in mind that’s a bare environment and your mileage will vary here as well. In my internal environment I was able to speed my logins up from around 75 seconds to 23 seconds. This is keeping in mind that our internal environment has about 847 GPOs and isn’t optimized at all. In my customer facing CSP environments I have gotten about a 75% improvement time in the environments that I have implemented these changes.

Take a look at my detailed UPM policy is here

Jan 312013


I’ve been running in my 6/6.5 environment since the beginning with UPM and didn’t even realize that the cookies were not saving properly. Apparently this is a known issue and the fix is simple! You need to add 2 things to your UPM Group Policy object. First, Add “AppData\Roaming\Microsoft\Windows\Cookies” to the “Folders to Mirror” policy. Second, enable “Process Internet cookie files on logoff” under the “Advanced settings” folder. When the user logs out and back in again, UPM will start properly processing cookies. Note: This does add a couple of seconds to the logoff time for users. Keep in mind if adding this to an existing environment that it could add minutes to the logoff time the very FIRST time a user logs off if they have a lot of cookies.

Dec 102012

Orazz from CitrixIRC found a great forum post that really made an impact on our environment. In a nutshell, when using the 2008 R2 Optimization Guide for XenApp and the Citrix Profile Manger, there is a registry setting that causes the UPM to timeout. A lot! After making the changes below, I noticed an immediate improvement in performance of the UPM. Logon/Logoff times have been reduced significantly. I’m also hoping this is going to lower the profile corruption issues that also pop up from now and again. We don’t have many since upgrading to UPM 4.x, but we still do have some.

  1. Upgrade to UPM 4.1.2
  2. Change HKLM\System\CurrentControlSet\Control\FileSystem\”NtfsDisable8dot3NameCreation” from “1” to “0” ( I did this using a GPP object as part of the optimization guide. I simply edited the GPP and changed to “0”)
  3. Backup and delete the keys from “HKLM\Software\Policies\Citrix\UserProfileManager”
  4. Reboot

Upon rebooting I verified the keys were recreated, and the NtfsDisable8dot3NameCreation was set to 0.

Note, some interesting changes in UPM 4.1.2 also. We use “Delete locally cached profiles on logoff”. This process now takes about 3 minutes for the folder to delete from the XenApp server. This is part of the new design. See UPM 4.1.2 in http://support.citrix.com/article/CTX134616

Citrix Forum Post