Feb 122021

Update Feb 11, 2020

In my First Blog post here Part1 I showed you how to set up Windows Deduplication on Server 2016. This second series will show you my production results and what I gained in space-saving

I estimated 18.5% in savings in the first post. However, I got 23% back, I think that is good in my opinion

I enabled Windows Deduplication on my production File Server Part1

Here is the drive space before, windows deduplication was running.

Ever so often I would run get-dedupstatus to give me an idea of what I am getting back

After Deduplication was run on 4TB Drive. As you can see I got back some good space

Now I wanted to take it one step further, and shrink the VHDXs. (Running it manually this time around)


I got back just a tad over 1 TB and some change overall. I take that as a win for now. Soon very soon, I will be moving a lot of this to Nutanix files, then we can see the difference if any 😊 of Those who use Nutanix AHV and Nutanix Files understand the awesomeness it offers. 

Nex day Checks on February 12,2021

Let’s check on the Environment, and confirm logins are not slower, and that the schedule is set incorrect nothing is running during the day.

My schedule is at 10pm = Check

I can confirm it’s not running and when the last time it ran is = Check

Monitoring the event log

“Monitoring the event log can also be helpful to understand deduplication events and status. To view deduplication events, in File Explorer, navigate to Applications and Services Logs, click Microsoft, click Windows, and then click Deduplication.”

“If the value LastOptimizationResult = 0x00000000 appears in the Get-DedupStatus |fl Windows PowerShell results, the entire dataset was processed by the previous optimization job”

Start time

Finished time

Citrix VAD (Fslogix) Login times. 1.6 seconds to attached the FSLogix profile.

Checking in Control up and things seem to be as they should before this was enabled. If you don’t have Control up, you can use Director. You can use the script as well to achieve some login measurements with just powershell


Analyze logon duration script just got more powerful | Citrix Blogs

As you can see, these are just some built in tools you can use. There is really no reason why you should not have this setup. Always test things and make sure you understand what it is that it’s doing, so you don’t break things



Monitor and Report for Data Deduplication | Microsoft Docs

Cleanup Jobs

Cleanup unused FSLogix Office 365 Containers – dready’s Blog

Delete Inactive FSLogix Profiles using PowerShell – hallspalmer_Blog (wordpress.com)

Delete old Profiles script

GitHub – FSLogix/Invoke-FslShrinkDisk: This script will shrink a FSLogix Disk to its minimum possible size

Dec 222020

I was recently tasked with moving some PVS target/vDisk to a new PVS environment. There are many ways to achieve this. However, this is how I migrate devices from one PVS Farm to another. I am sure there are better ways to automate this as my blog is just a simple way to get it done. Migrating PVS targets to a new PVS Server. Another way I have done it in the past was add new PVS servers into an existing Farm, then go through the actions to make them the main servers, and of course decom the old ones. This is a very simple task, and most people know this. But if not, they will help.

Open your PVS Console, and select the PVS vDisk, then click export.

Select the lowest version to grab the vDisk Chain

You will see a Filename.xml get created. This is a manifest file that will instruct the new destination PVS server to inject the version in.

For me I like to create Stores for all my different vDisk.

Give it a name

Check all the PVS Server that will contain the vDisk

Create the folder in the given location that you are storing the vDisk and Validate the paths.

I leave the default write cache location in the area it selects, as we do use the old legacy ways of the Write cache to server.

Now I just copy the Connects form the original Server to the destination

At this point I open of the PVS console and go to vDisk pool

Right click and Import

Select the store you create earlier, and Select a PVS server that you copied it to, and click search

Or you can import it from the Store, so you don’t have to select anything and take the change of getting something wrong.

Click Add and close

Click ok, after vDisk was added

Now you can see the Vdisk

For me I use a dedicated VMware device for updating my master images and such. I am going to move the VMware device over to the new PVS server and update the subnet and MAC as well to reflect a new subnet we just added.


Change the Port group and note the MAC

Now at this point I manually create the Device in the new PVS Server.

Add the new MAC, Update the vDIsks area to the vDisk you imported in.

Change the Type to Maintenance

Now because I use the ISO BDM method, I need to update it to the new BDM to the new PVS Boot path.

If you have more than one new PVS server, make sure you copy the vDisk files to the second server as well, or when it boots up based on the default load balancing, it will hit the second server and tell you no vDisk found.

Check and make sure the replication status is green on both servers

On the device, you will need to reset the Machine account from PVS, to recreate the Domain trust password

Now, boot the Maintenance Machine up and it should stream to the new location. Found the vDISK

Typically for moving all the targets I would do something like this, then I would edit the MAC addresses so they would align with the new subnet that I change from. 

How to Migrate PVS Target Devices | | Apps, Desktops, and Virtualization (kylewise.net)

For this situation, I can now create all new devices that will have the same vDisk. I will create a new Machine Catalog/Deliver Group. You can also use the same one if needed. I use FSlogix, so the profile data will be intact for the user, the user will not even notice anything has changed as far as the devices name or its moved to a different PVS server.

May 062020

I recently ran into having to create a chunk of MCS dedicated machines for this COVID-19 situation the world is in. MCS Dedicated machines are very different from MCS Pool machines. One of the HUGE differences is updating the machine’s images and updating the targets. As your aware MCS Pooled is very similar to PVS and it’s a nice update feature for the PVS/MCS targets. But MSC dedicated machines are not the same. 

This Blog is around MCS Dedicated Full Clones only and updating the Master image to update only new created machines.

Dedicated desktops are assigned to individual users and the data and settings will persist on the desktops. Optionally, the Citrix Profile Management solution can be used to store the user profile and data on central file servers. For dedicated desktops there is a new option available under Desktop OS Catalogs virtual machine copy mode, “Use full copy for better data recovery and migration support, with potentially reduced IOPS after the machines are created”.

“When you deploy the image, you will notice that MCS will do a full VMDK copy of your snapshot chain into a folder of every datastore that is defined in your hosted XenDesktop environment. This makes desktop creations extremely quick when scaling out additional VMs because it 1) negates the need to potentially copy VMDKs across datastores during desktop creation and 2) negates the need to consolidate snapshots during creation. The folder will typically be the machine catalog name + basedisk + random datastore identifier assigned by XenDesktop. This applies to all MCS images; static and pooled.”

You can see the base Snapshot MCS created called Citrix_XD_Name. This is the initial snapshot Studio-MCS makes. But ideally can keep them all around. So my steps are as outline below

Deleting all Snapshots. (Deleted All Yes) I didn’t want any old stuff floating around.

Create new snapshot

Now I’ll update all tools, software and whatever I need to update.

Let check the Provision Scheme so I can get the Provisioning Scheme and the XDhyp information and display the list of snapshots on the virtual machine:

I copied it from PowerShell and put it in OneNote so I could see what I was looking for. As you can see here it still shows my old snapshots. We will update that.

Note to find the ProvisiongSchemeName   (Its list in the Get-ProveSheme) Command. Keep this name for later

  1. Now at this time, I need to run this

a. Get-ChildItem -Recurse -Path ‘XDHyp:\hostingunits\%hostName%\%vmName%.vm’

b. This will list the Snapshot that is associated with the VM itself

c. For me it’s this:

d. get-childitem -Recurse -Path “XDHyp:\HostingUnits\XA_XD Netwrk Connection VS1VC01_PROD_176\XD7MSTRHR.vm”

  1. Then my output is

*Note* you can see that it shows my snapshot listed

  1. I need to take the “Full Path” and note it for the next command.
  1. Second command is:
  1. Publish-ProvMasterVmImage -ProvisioningSchemeName “%provisioningSchemeName%” -MasterImageVM “%templatePSPath%”
  2. For me Its:
  3. Publish-ProvMasterVmImage -ProvisioningSchemeName “Citrix Human Resources Desktop” –masterimagevm “XDHyp:\HostigUnits\XA_XD Netwrk Connection VS1VC01_PROD_176\XD7MSTRHR.vm\ImageUpdate.snapshot”

While this is running in my Hypervisor you will see this.

Once it’s completed you will see

Now Run Get-ProvScheme

These updates will only apply to new machines created from the MCS full Clones. It will not update previously created ones. That is the downfall of MCS Dedicated full clones. 



Apr 222020

MCS Static Reboots in Studio

During this COVID-19 I had to build 500 VDI desktops. During this time, I could only use dedicated machines because of how some software is licensed. I didn’t really care for this, but I had to do what was needed to provide remote support. This was my experience, in getting an automatic reboot with MCS Static (dedicated machines) 

  1. Set the DG to this
  2. I set the peak hours to be 24/7
  3. Then I set when the user logs off it will shut down the machine
  4. I will explain this in more depth below
Machine generated alternative text:Edit Delive Power manage machines: Grou Wee kdays Studio Machine allocation Desktop Assignment Rules Delivery Type User Settings Sto reFront Scopes Power Management Access Policy Apply Peak hours: 00:00 During peak hours: When disconnected When logged off During off-peak hours: When disconnected When logged off 03:00 06:00 mins nuns nuns 09:00 No action Shut down No action 12:00 15:00 18:00 21:00 Cancel

5. We have a disconnect timer set to 5 minutes, after 5 minutes it will log the users off, then based on “when logged off-Shutdown” select above will kick in sending the machine in a shutdown state

Machine generated alternative text:Disconnected session timer User setting - ICA\Session Limits Enabled (Default: Disabled) s6sion timer interval User setting - ICA\Session Limits 5 minutes (Default: 1440 minutes)

6. In order to have machines power on automatically during peak hours run the following command against the Static/Persistent Desktop Delivery Group. I had to set the CLI in each DG to make it seem that the machines are assigned and to turn back on. I found this command on George Spiers site.

Set-BrokerDesktopGroup -Name “test Desktop” -AutomaticPowerOnForAssignedDuringPeak $true

7. What the command does is it will tell the Catalog to turn the machines back on during the peak hour windows. Being our peak hour windows is set for 24/7. I guess you can say, it created a reboot schedule 12

8. Here is an example of a Session that is in a Disconnected stated.

9. Session time in disconnected state (in 5 minutes it will log me off, and trigger a shutdown)

10. After the timer hits 5 minutes you can see what happens below.

11. In VMware the results, Once the Disconnect time happens, or the users actually logs off.

12. VDA registered 30 seconds later.

13. Desktop Launched successfully. 7:41 pm

Oct 182019

Update 10/29/19: Added search (username/userfullname) to the Sessions tab.

Studio always seems extremely sluggish to me when trying to navigate between different areas. I’m always waiting a few seconds for the refresh circle to go away every single time I navigate somewhere new.

Most of the time I just need to put a machine in/out of maintenance, perform a power action, or logoff/disconnect a session. I found that power shell is MUCH faster, so I wrote a new little tool.

.net 4.5
The broker admin powershell snapin (available on the install media -alternatively you can run this on the delivery controller itself and use localhost as the connection string)

You can select each server/desktop/session individually, or select multiple. Then simply right click and select the operation to perform. I have tested this on versions 7.15 through 1906. Note: There is no warning! When you select the action to perform it will just do it.
Here is the download link

Operations allowed (depending on state):
Machines – turn on/off maintenance, shutdown, restart, reset, poweroff
Sessions – Disconnect, Log Off

Feb 212018

I plagiarized David Ott’s script for migration of Citrix Profile Manager (UPM) profiles to FSLogix and created it for Local Profiles.

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.

This requires using frx.exe, which means that FSLogix needs to be installed on the server that contains the profiles. The script will create the folders in the USERNAME_SID format, and set all proper permissions.

Use this script. Edit it. Run it (as administrator) from the Citrix server. It will pop up this screen to select what profiles to migrate.

#### EDIT ME
$newprofilepath = "\\domain.com\share\path"

#### Don't edit me
$ENV:PATH=”$ENV:PATH;C:\Program Files\fslogix\apps\”
$oldprofiles = gci c:\users | ?{$_.psiscontainer -eq $true} | select -Expand fullname | sort | out-gridview -OutputMode Multiple -title "Select profile(s) to convert"

# foreach old profile
foreach ($old in $oldprofiles) {

$sam = ($old | split-path -leaf)
$sid = (New-Object System.Security.Principal.NTAccount($sam)).translate([System.Security.Principal.SecurityIdentifier]).Value

# set the nfolder path to \\newprofilepath\username_sid
$nfolder = join-path $newprofilepath ($sam+"_"+$sid)
# if $nfolder doesn't exist - create it with permissions
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

# sets vhd to \\nfolderpath\profile_username.vhdx (you can make vhd or vhdx here)
$vhd = Join-Path $nfolder ("Profile_"+$sam+".vhdx")

frx.exe copy-profile -filename $vhd -sid $sid
Dec 202017

In my environment I have nearly 100 persistent MCS VDAs. Our developers, contractors, and even us IT people need the ability to change things on our VDI desktops (install/uninstall/set registry/create local IIS sites/etc.) and have them persist reboots. Luckily, the only software I have to maintain on these desktops is the VDA itself. That still means when Citrix releases a new version that I want to move to, I have to upgrade almost 100 individual desktops. The last time I had to do this I wanted to rip my hair out, and decided to write a script to automate the task. It has saved me TONS of time, so I want to share it in hopes that it can save someone else some time (and hair).

I wrote the script specifically for my MCS environment, which runs on XenServer, but with a little tweaking it can be modified for any environment.

How it works (the short version):

  1. Gets the computer(s) you set – can be manual input or a delivery controller query
  2. On each computer it will create 2 scripts, and 2 scheduled tasks
    1. The first script loads auto logon info into the registry
    2. The second script handles the vda removal and install
  3. One scheduled task runs once to run the first script and reboot
  4. The second scheduled task runs the second script at logon (first script sets up a user – in my case the local administrator – to logon automatically)

Most things are explained in the script, and this time I’ve also created a youtube video to go through it all/show it in action.



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!

Mar 312017

In my environment I have about 300 provisioned desktops, and when I update the vDisk sometimes it can take a while (days) before all of the VMs get the latest version.  Especially, in the case of a roll back I need a good way to get all of the VMs which are on the wrong version (and are waiting for a session) to boot to the correct version.

I think powershell version 3, but since I did it with v4 I’ll say 4+
PVS powershell module installed (learn more here)
Powershell remoting enabled on your delivery controller (also need to supply the name in the script)

What the script does:

  1. Gets a list of the Collections in your PVS environment, and outputs it to out-gridview so you can select the collection you want to focus on
    1. If you hit cancel the script ends
  2. After your select the collection and hit ok it will get all of the devices in that collection which are powered on, and cannot access a maintenance/private disk image
  3. For each of the devices in that list it checks to see if they have the latest vDisk version, or if they have the correct OverRide version.
    1. If they do then it tells you the device is on the correct version, and moves on to the next device
    2. If they do not then it will pass the device name to the check function, and after moves on to the next device
      1. invokes powershell on the delivery controller to see if the VM is in use (powershell remoting required)
        1. If it is, it tells you it is in use and does nothing
        2. If it is not it will reboot the vm, and tell you

Here is the script!  Remember to test it before using it in a production environment.


Feb 092017

I recently ran into an issue after upgrading my XenDesktop environment to 7.12 from 7.11.  Prior to that update I was able to create MCS desktops in my XenServer pool with no issues.  After upgrading to 7.12 the newly created VMs would not register with the delivery controller, and according to XenServer they did not have the tools installed.  I found that the network card didn’t even appear in Network Connections, and in device manager it showed up as a Realtek adapter instead of the XenServer PV device it should have.

After further investigation I found that the new VMs were created missing some things in XenServer if compared to VMs which were working (xe vm-list name-label=<name of vm> params=all).  I posted on discussions.citrix.com to see if anyone had run into this issue before, and Carl Stalhood pointed me to this post.

Apparently, there is a private hotfix that will correct the problem, but it requries you do delete/re-create the machine catalog (which shows as the answer to the problem on the thread).  Reading through the post Paul Browne gives a much better/easier solution:
“Also in the short term to get your VM`s working correctly.

Shutdown the VM
putty or console into the XenServer

xe vm-list

(find UUID of the Vm you wish to fix)

xe vm-param-set has-vendor-device=true uuid=<UUID of the VM>

It should now work as expected.”

I wrote this PowerShell script to perform the operation, that Paul gives above, automatically across multiple VMs.  Requires Powershell v3, scripts enabled (set-executionpolicy to change it), and XenCenter to be installed on the machine the script is run from.  Read the comments of the script to see an explanation of what the script is doing.