One of my customers with a very large XenDesktop deployment (5000+ desktops) recently had a need to remove a list of VM’s from their environment… several hundred desktops spread across multiple groups. Obviously doing it manually wouldn’t be very quick or easy, so we set out to find a powershell solution to the problem.

We initially tried a direct approach, pulling the list of computer names from a text file and iterating through the list:

  • Query for a reference to the desktop using Get-XDVirtualDesktop
  • Query for a reference to the group that it’s in using Get-XDDesktopGroup
  • Remove the desktop from the group, and do the necessary Set-XDDesktopGroup to apply it
  • Repeat for the next item in the list.

This approach performed terribly… Get-XDVirtualDesktop is a very expensive query, especially in a 5000 desktop environment, so the result of running this script was IMA running at 50-100% with rapidly climbing menory… to the point where it hung. Not good.

With a little help from some in-house experts, we came up with a different approach… avoiding Get-XDVirtualDesktop altogether:

  • Get the list from a text file and store it in an array
  • Get the list of desktop groups and store that in another array
  • Iterate through the list of groups, checking each one’s list of desktops for matching members in the original list. Store the result in a third ‘$desktopsToRemove’ array.
  • Iterate through that list doing the removes
  • Apply the changes with Set-XDDesktopGroup
  • Move on the the next group

This worked much better… code below. Enjoy!

# Remove a list of desktops from XD4 desktop groups

 $inputList = Get-Content C:\temp\removevms.txt
 $formattedList = @(forEach ($item <span class="code-keyword">in</span> $inputList) {'HOMEOFFICE \' + $item + '$'})
 $groupList = Get-XDDesktopGroup

 ForEach ($desktopGroup <span class="code-keyword">in</span> $groupList) {
     $DesktopsToRemove = @( $desktopGroup.Desktops | where { $formattedList -contains $_.Name } )

 <span class="code-keyword">if</span> ($DesktopsToRemove.Length) {
       foreach ($desktop <span class="code-keyword">in</span> $desktopsToRemove) { $desktopGroup.Desktops.Remove($desktop) }
       Set-XdDesktopGroup $desktopGroup
    }
 }