Migrating Ivanti/AppSense profiles to FSLogix Profile Containers

Migrating DesktopNow to FSLogix has always been fiddly. Let’s see how we can do it!

Ivanti User Workspace Manager (or AppSense DesktopNow) has a product called Environment Manager Personalization Server that is used for storing users’ profile information in an SQL database. Whilst a very fine product (I cut my blogging teeth writing about AppSense, so still have a great deal of experience with it and fondness for it), there are a lot of people moving away from it towards the like of FSLogix Profile Containers – mainly purely from a cost perspective. I still think DesktopNow has its place – for fine-grained control of the user environment, you can’t go far wrong – but as I have had to perform migrations for a couple of customers recently, I thought I would write up the process I used to do it.

Introduction

Let’s just start by saying that the migration process isn’t particularly straightforward. If I was someone like Jim Moyle (or one of the many other God-level scripters out there in the EUC community), I would just write a script to pull the information straight out of the SQL database and build a new profile. But unfortunately for you, I’m not. So the process I am using involves a bit more fudging than you may like. However, I have used this in the wild with success on a few occasions now, so I think this should work for you, if you can follow the same process (and you’re always welcome to drop me an email and get me to do it for you, if you have any problems).

Firstly, we need a three-tiered setup to accommodate this. We need our existing Ivanti UWM-managed infrastructure, we need our new FSLogix-managed infrastructure, and we also need an intermediate area which has both Ivanti and FSLogix installed to perform the migration. The reason for this is because most people use Ivanti Personalization Server combined with mandatory profiles, and we can’t migrate data out of mandatory profiles (because they’re utterly non-persistent). If you’re using Ivanti with local profiles, you may be able to skip the need for the intermediate area, but generally in RDSH or VDI environments local profiles are uncommon (unless you’re doing pooled non-persistent).

Also, we have performed the testing and demoing of this on Citrix Virtual Apps, but the principles should work equally well for other setups – whether these be VMware, Parallels, Windows Virtual Desktop, physical machines, cloud-hosted devices, etc.

We are going to use the following acronyms extensively:-

PMO – Present Method of Operation, referring to the existing solution with Ivanti/AppSense being used for profiles

IMO – Intermediate Method of Operation, referring to the intermediate area that users will need to access to trigger the migration

FMO – Future Method of Operation, referring to the new image with FSLogix Profile Containers being used for profiles

Pre-requisites

Ivanti/AppSense version

Unfortunately, more bad news here. This process relies on the ability to move data from one Personalization Group to another within Ivanti/AppSense. If you’re on version 10.x or higher, than all is good – Personalization data is now shared between Personalization Groups (see this article for more information about this – logon required). If you are still on version 8.x – this is a major stumbling block. When the user is moved from the PMO to the IMO group, you will need to manually migrate the Personalization data from the PMO Personalization Group into the IMO Personalization Group. I am reliably informed that Ivanti support may be able to provide a script that can help with this, so if you can get hold of it, this may help you out a bit here. Otherwise – you have to copy the data manually across using Personalization Analysis, and personally, I’d rather just start the users with brand new profiles then spend the time to do that. Update – I’ve had a good long think about version 8, and I now think you could maybe do this with a “big bang” approach instead…see the “Version 8 Considerations” section near the end.

However, if you are on version 10.x – or able to get to version 10.x – then by all means, carry on!

Active Directory Groups

I created three AD groups to go alongside my three slightly different images – PMO_Group, IMO_Group, and FMO_Group.

Citrix Virtual Apps config

I also created three different delivery groups and desktops within Citrix Studio to align with these groups, each of these desktops served by a slightly different image.

Images

The main differences between the images are summarized below:-

PMO – this is the image used currently and has the Ivanti UWM standard agents and configurations installed

IMO – this image has the Ivanti UWM standard agents and configurations and is the same image, with a few additions

  • FSLogix Apps should be installed, but it should NOT be configured. The GPOs that control FSLogix are NOT applied to these servers (so there will be no value of Enabled in the HKLM\Software\FSLogix\Profiles key).
  • PowerShell Constrained Mode should NOT be turned on. The commands used to migrate the user profile require Full Language Mode. If you have enabled Constrained Language Mode (I recorded a video on it very recently!), then use a filter on the GPO that enables it to stop the policy from applying to the IMO server or servers.
  • The Group Policy Object for “Only allow local profiles” needs to be Enabled, which sits in Computer Config | Admin Templates | System | User Profiles. Ensure that this is turned on, because otherwise the mandatory profile will be purged from the machine and you will be unable to perform the migration.
  • The Ivanti/AppSense configuration applied to this machine should write a local folder called c:\UsersToConvert\%USERNAME% every time a user from the IMO_Group logs on. This will be used as the trigger to migrate their profile after they have logged out. This can be added to the PMO configuration and simply rely on a conditional check for the IMO_Group membership (as below)
  • You should also set the GPO for “Delete user profiles older than a specified number of days on system restart” on this server or group of servers, and set the value to 1. Dependent on how many users you are migrating and how your machines are deployed, you may want to restrict the number of local profiles being saved to the machine. Adding this GPO (which also sits in Computer Config | Admin Templates | System | User Profiles) will keep the number of stored profiles down. You could also delete them manually if required.
  • Finally, you need to set up a Scheduled Task on the IMO image which will trigger a migration script to run when users log off (event id 4647). This can be baked into the image or deployed via GPO or even PowerShell, it is up to you how you do it. The contents of the script and the setup of the Scheduled Task are detailed more later in the article.

FMO – this is the image to be used going forwards, and has the same applications but NO Ivanti agents or configurations, and has the FSLogix Apps agent installed and FULLY configured (enabled with all standard settings and pointing to the file share where the FSLogix profiles are stored)

Personalization Server configuration

Also, you need to make sure you have two Personalization Groups set up within the Ivanti Personalization Server console, with a few slight differences.

They should have exactly the same Application Groups and Windows Settings Groups applied to each.

However the PMO Personalization Group should have its membership rules applying to the PMO_Group from AD

And the IMO Personalization Group should have the same applied to the IMO_Group from AD

Also, the IMO Personalization Group needs to have Profile Migration turned on as below.

Finally, you MUST make sure that the IMO Personalization Group sits above the PMO Personalization Group in the list so that users do not end up in the wrong one.

The process

Hopefully you might be starting to get a feel for how this is supposed to work πŸ™‚ The diagram below may possibly make the process a bit clearer.

The idea is that users are manually moved into the IMO_Group and removed from the PMO_Group when they are ready for migration. You can do this manually or in an automated fashion and move as few or as many as you wish.

Once they are in the IMO_Group when logging on to Storefront or ADC they are now offered a different desktop, the IMO Desktop. This looks to all intents and purposes the same but as they log on it adds their username into a folder for migration, and then when they log off, a Scheduled Task is triggered that launches a PowerShell script to perform the migration. After migrating, the same script clears their username from the folder, removes their mandatory profile entries, removes them from the IMO_Group and adds them to the FMO_Group.

Once this is done, next time they access Storefront/ADC or refresh it they are now logged on to the FMO Desktop, and this uses FSLogix only with the migrated VHD and should bring across all of their settings.

The migration script

Firstly, you will need to adjust the script slightly, mainly for your FSLogix profile share, your AD group names, whether you want to create VHD or VHDX files, and the parameters for the frx.exe command that will do the migration. The parameters for frx.exe with the copy-profile switch are documented here – you may want to adjust them around such things as maximum VHD size, dynamic assignment, etc.

Secondly, you may notice some severe fudging here (the source for this script is Ryan Gallier’s port of David Ott’s script which I found on CitrixIRC). I had to put a 60-second delay in because the profiles sometimes take a long time to unload (UPM admins will be very familiar with this sort of problem). Also, it isn’t a mistake – yes, I run the frx.exe command twice. Sometimes, halfway through creating the migrated disk, the VHD(x) simply disappears. I have no idea what causes it – but running it again seems to work OK. I said this was a fudge πŸ™‚

I normally just save this script on the network somewhere and push it down to the IMO server(s) using Group Policy Preferences – again, up to you how to do this. Obviously wherever you put it, you will need to reference it in the Scheduled Task (and I find that storing Scheduled Task action scripts locally always works much better than those on the network). Here’s the PowerShell you will need to edit for your own environment:-

# Migrate local profile into VHD file share at logoff

# Set destination file path here
$destinationprofilepath = "\\UKSLDC003\FileStore\Profiles"

# Set PATH variable
$ENV:PATH=”$ENV:PATH;C:\Program Files\fslogix\apps\”

# Pull names of users scheduled for migration from c:\UsersToConvert folder. This folder has the usernames added as the users log off from the IMO server
$usernames = gci c:\UsersToConvert | ?{$_.psiscontainer -eq $true} | select -Expand fullname | sort

# Feed user ids from usernames variable into loop

foreach ($user in $usernames) { 
$userid = ($user | split-path -leaf)
$sid = (New-Object System.Security.Principal.NTAccount($userid)).translate([System.Security.Principal.SecurityIdentifier]).Value

$targetpath = join-path $destinationprofilepath ($userid+"_"+$sid)

# If targetpath does not exist, create it and set permissions
if (!(test-path $targetpath)) {New-Item -Path $targetpath -ItemType directory | Out-Null}
& icacls $targetpath /setowner "$env:USERDOMAIN\$userid" /T /C
& icacls $targetpath /grant $env:USERDOMAIN\$userid`:`(OI`)`(CI`)F /T

# Set full VHD path including filename of VHD (use VHD or VHDX file extension here as appropriate to your environment)
$vhdfullpath = Join-Path $targetpath ("Profile_"+$userid+".vhdx")

# Pause for 60 seconds to allow profile to unload before starting to migrate it
start-sleep 60

# Perform profile migration
frx.exe copy-profile -filename $vhdfullpath -sid $sid

# This is not a mistake - we need to run the migration command twice, because sometimes (not sure why) it starts to create the disk and then the disk disappears completely. Have been unable to trap the error, so running twice to make sure
frx.exe copy-profile -filename $vhdfullpath -sid $sid

# Remove from IMO group - EDIT the group name as required here to fit your environment
net group IMO_Group $userid /delete /domain

# Add user to FMO group - EDIT the group name as required here to fit your environment
net group FMO_Group $userid /add /domain

# Remove mandatory profile paths from user object (this section can be removed if not using mandatory profiles)
# The tsprof command will only work if being run from a system which has RDSH installed, but if the target systems are not RDSH, then the RDSH Profile path will not be used anyway
net user $userid /ProfilePath: /domain
tsprof /UPDATE /DOMAIN:$ENV:USERDOMAIN /PROFILE: $userid

# Delete folder that triggers conversion (otherwise it will be constantly trying to re-export the local profile)
remove-item c:\UsersToConvert\$userid -Force
}

The Scheduled Task

Once you’ve gotten the script onto your IMO servers, you now need to deploy a Scheduled Task to invoke it at logoff. I did it manually like this.

Create a new Basic Task in the Task Scheduler

Set the trigger to “When a specific event is logged”

Set the event properties as below (note – this was done on Windows Server 2019, other operating systems may have different properties here)

Select “Start a program” as the Action

Select powershell.exe as the program, and add “-ExecutionPolicy Bypass -File c:\Path\toyourscript.ps1” as the arguments

Select “Open Advanced properties for this task when I click Finish”, then click Finish

Make sure the task is set to run with an administrative account, that it runs whether the user is logged on or not, it runs with highest privileges, and is configured for your OS version. Also, make sure that the account it is running under, as well as having admin privileges, is able to write to the file share where it is going to create the profiles, and can also add and remove users from AD groups and change user object properties (as it does these tasks as part of the cleanup).

Enter the password when prompted and the task should now be ready to run the script when users log off. It will actually run for every user, but unless there are folders in the c:\UsersToConvert folder nothing will be done and it will simply exit.

Version 8 considerations

I know I said doing this from version 8 was ridiculously hard, however, having had time to think, you could do this if you were willing to accept a “big bang” approach. Essentially, because version 8.x doesn’t share Personalization data across the Personalization Groups, your PMO systems would all have to be turned into IMO systems and all of your users migrated in one big bunch. So you’d have to set a date, turn on the profile migration on your personalization group, get FSLogix Apps installed but not configured on your existing servers, set the GPOs for local profiles, do all the AD and Citrix config, update the Ivanti configuration and deploy it, and then set about the migration en masse. This should work OK, as long as you are aware you have little control over the volume of users being migrated. The biggest issue I can see is impact on storage and performance as the user migrations are performed and the potential of jamming up your servers with lots of copies of local profiles as they are left behind. You can easily get around the local profiles issue by adding a delprof2.exe command to the end of the migration script, but the storage impact would have to be assessed. However, if you wanted to migrate version 8 profiles in situ (as long as it is a new enough version that it has the profile migration setting!), this should work OK. You could even use this two-stage big bang approach on 10.x versions if you were brave, but just be aware you are giving up an aspect of control over this.

Time to test!

This is all you need to do (I actually said that with a straight face). Yes, there’s a lot of prep, but once you get it done and working for one user, it should be seamless for the rest.

Given that I seem to have a penchant for video tutorials these days, here’s me trying to run through that for everyone.

Summary

So hopefully this should allow you to perform the migration from Ivanti to FSLogix on a profile level without too much trouble. As I said, thanks to Ryan Gallier and David Ott for their initial work on the migration script – community always rocks for sharing!

If you find this a bit of trouble, I’m always willing to answer emails and comments about it – if you’re really stuck, you can always ask me to come down and visit, but I will demand beer money as recompense πŸ™‚

Cheers!

18 comments

  1. Hi
    That’s a really nice post about migrating profiles away from AppSense Personalisation to FSLogix profile containers.

    But isn’t that only half the migration story away from AppSense? I’m unfamiliar with FSLogix but how would you go about migrating AppSense EM Policy settings across to FSLogix? Does FSLogix have something similar to EM Poilcy or does it rely on Group Policy?

    I’m thinking if the latter, you lose features like “process started” from AppSense and Group Policy can be much slower to process. If I was migrating away from AppSense I’d probably look at pulling all the settings from the EM Policy using something like the Configuration Profiler and trawling through the resulting PDF for all the different settings being applied by EM Policy. However, the thought of migrating these all across to legacy Group Policy is rather daunting.

    That’s why I was wondering if FSlogix has an “EM policy” equivalent or do you know of any other UEM solutions that handle both the AppSense “Profile” and “Policy” migration in 1 single package?

    1. FSLogix doesn’t do policy. But you can just use Group Policy itself, or a third-party tool like Citrix WEM or PolicyPak. if I had to migrate policy settings, I would use PowerShell to pull out the AppSense settings from XML and then feed them across. Bit of a fiddly project but quite doable.

      Bear in mind that if you get asynchronous policy processing working for user GPOs, you already have GPOs now processing “after” logon, so Ivanti loses a bit of its potency. If you wanted further offloading, use a Scheduled Task or WEM.

      “Process Started” barely saves you anything, though. You’re talking milliseconds.

  2. Thanks for the reply. Using PowerShell to extract and migrate the EM Policy is a good idea and a possible option I guess. Fair point about GPO processing.

    Perhaps I’m just a bit of an AppSense evangelist but I much prefer EM over Group Policy. We use a lot of Process Started routines to apply application fixes on the fly (PowerShell, registry hacks etc.) and likes the diversity it gives you over Group Policy for so many different settings. It would just feel a little strange reverting back to basic Group Policy to configure the user environment having used AppSense EM for so long. The fact its in 1 easy to read Policy also helps with troubleshooting.

    Something like Citrix WEM or PolicyPak are options but I can see my organisation going for FSLogix but opting for basic Group Policy, which isn’t as friendly or sophisticated as AppSense EM in my opinion., when manipulating the user environment.

    Out of interest, does FSLogix give faster logons than Appsense? A bit of a general question, I know. The place I work for is obsessed by “sub-30” second logon’s.

    1. The problem is complexity. AppSense makes sense if you’ve got the resources to constantly tweak it. Whereas with FSLogix just capture everything and off you go. GPO with GPP gives you a lot of power and if you go asynchronous then you don’t need to worry about offloading. Scheduled Tasks are now much easier to set up to run after logon to do further customization.

      I have a customer with 7 second Windows 10 logons that use FSLogix, and a lot of other tweaks besides.

    2. James, I have a couple of questions – a little different to the strategy you are putting in place – but when doing this for non-persistent desktops, this script is not running at logoff (or the logoff is happening too quickly) The endpoint is Windows 10 NPP and I have checked that the eventid is correct 4647 and that is displayed in the Security tab within the event logs. The setup has been configured as outlined (albeit targeting a NPP as opposed to a XenApp server – but noticed that if I am logged to the VDI and try and run the powershell script – it is showing frx.exe not working directly in powershell). What other mechanism (apart from creating a scheduled task on the master image) would you use to force this to run the script? Any ideas? Trying to migrate from Ivanti Personalization 10.1 to latest FSLogix. Have confirmed that the FSLogix is working as expected.

      1. Sorry, what do you mean by NPP? If the config is complicated feel free to email me at kz20fl [at] gmail [dot] com if you want.

  3. Hi, James,
    first, great article.. Thank you very much for your work!
    We also want to migrate our user profiles from Ivanti EM to FSLogix. But we would like to keep the EM policy for now. And here is the problem:

    If Ivanti EM and FSLogix are running parallel (EM Config without a registered pers. server) i am not abtle to start outlook anymore
    The process starts, but there is no window…
    If I stop the EM or FSLogix service, Outlook starts again.

    Out environment:
    Windows Server 2019
    Ivanti EM 2019.1 SP1
    Latest FSLogix release.
    Citrix Applayering 2001 and PVS to create the images
    CVAD 1912 LTSR

    Do you have any ideas about this?

    1. So you want Ivanti to manage policy and FSLogix for personalization? It sounds like Ivanti is hooking the Outlook process for Personalization. Have you tried excluding Outlook from the dll that does the hooking (it used to be called pvc.dll, not sure what it would be now)

  4. Hey James,
    As ever, great article and thanks for writing. We’re about to migrate from EM to profile containers, do you have any tips for how the above can be tweaked for instant clones, would the same principles apply..?

    1. All of this is pretty much on the user level so not sure anything would need to be changed? Or is there a particular part of it that seems problematic?

  5. James,

    Great article I’ve done about 300 of these migration with the added hurdle of jumping from Win 7 to Win 10. We ended up creating two powershell scripts to accomplish this task. Our export script would start and close all the apps we were trying to copy over to Win10. Then it would copy the data on to their redirected folders. We would remove their redirected folders and have them login to Win10. Then run the import script which would copy those settings we wanted to move over. It was a lot of hit miss to get it to work as needed but it does it very well.

  6. Yes that would be very helpful, if you could let me know when that will be as I have a deployment starting soon

    1. Hi Martin, I will add it to my backlog but given current workloads I am unable to commit to a specific date. However – the process involves migrating the AppSense profile back to a local profile. At that stage, you would simply configure UPM with the “migrate local profiles” option and get the user to log in, at which point the local profile would be migrated to UPM. The triggers should be the same, just the actions are slightly different.

        1. See the “Personalization Server configuration” section of this article. You need to turn on the setting for the Personalization Group to migrate back to a local profile.

Leave a Reply to Matt Hinchy Cancel reply

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