Here’s a quick list of Powershell commands I find myself using frequently. I’ll keep this updated.

Get a list of all brokered connections

Get-BrokerConnectionLog | Sort BrokeringTime

I always sort by BrokeringTime because the order appears to be odd otherwise because the log is updated with the initial brokering time as well as the EndTime.

Add an application to multiple delivery groups

Add-BrokerApplication -Name "AppNameHere" -DesktopGroup "NewDesktopGroupHere"

Adding an application to multiple desktop groups is 100% supported, it’s just not exposed in the GUI as of XenApp 7.5. Otherwise, if you try to add an application that already exists, you’ll get “Microsoft Word_1”. Also note when you do this, you can also set a priority to different desktop group- by default, the priority is added as zero – take a look:

PS C:\Windows\system32> Get-BrokerApplication -Name "Notepad"
ApplicationType                  : HostedOnDesktop
AssociatedDesktopGroupPriorities : {0, 0}
AssociatedDesktopGroupUids       : {1, 2}
AssociatedUserFullNames          : {Domain Users, Jake Rutski}
AssociatedUserNames              : {lab\Domain Users, lab\jrutski}
AssociatedUserUPNs               : {, jrutski@home.lab}
BrowserName                      : Notepad
ClientFolder                     : AppCategory
CommandLineArguments             :

To set a different priority, use the ‘-priority’ argument:

Add-BrokerApplication -name "notepad" -DesktopGroup "Test Delivery Group" -Priority 5

View the SQL DB info for the XenDesktop site

Server=TESTSQL1;Initial Catalog=CitrixTestSite;Integrated Security=True

Monitoring Scripts

This script was used with a monitoring solution to return the count of unregistered machines, not in maintenance mode, powered on, and with a user assigned to the desktop:

(Get-BrokerDesktop -MaxRecordCount 2000 -AdminAddress yourddc.goes.here | Where {($_.RegistrationState -eq "Unregistered") -and ($_.AssociatedUserNames) -and !($_.InMaintenanceMode) -and ($_.PowerState -eq "On")}).Count
This script returns the count of session disconnections for the last 5 minutes – note that the polling interval for this script would be every 5 minutes. If you wanted to poll every 1 minute for example, change to AddMinutes(-1):
(Get-BrokerSession -SessionState Disconnected -AdminAddress yourddc.goes.here | Where {$_.SessionStateChangeTime -gt ((Get-Date).AddMinutes(-5))}).Count

Static Machine Addition

This script will get the ID of a VM, add it to the machine catalog with the CatalogUid of 3 and HypervisorConnectionUid of 2 (change these to match your needs); then assign a user and add to a catalog. Note a few variables used: $NewCluster and $NewVMName are specific to the path to the VM object; $NewVMName is the computer name of the machine.
$NewVMObj = Get-ADComputer -Server your.domain.controller -Filter {Name -eq $NewVMName}
Set-HypAdminConnection  -AdminAddress "yourddc.goes.here"
$XDVMId = (Get-Item "XDHyp:\Connections\Your Cluster\Your.datacenter\$($NewCluster).cluster\$($NewVMName).vm").Id
# Add machine to machine catalog; add user to machine
New-BrokerMachine -AdminAddress "yourddc.goes.here" -CatalogUid 3 -HostedMachineId $XDVMId -HypervisorConnectionUid 2 -MachineName $NewVMObj.SID
Add-BrokerUser  -AdminAddress "yourddc.goes.here" -Machine (Get-BrokerMachine -SID $NewVMObj.SID).Uid -Name "YOURDOMAIN\$($NewUser)"
# Add machine to desktop group;
Get-BrokerMachine -SID $NewVMObj.SID | Add-BrokerMachine  -AdminAddress "yourddc.goes.here" -DesktopGroup "Your Desktop Group Here"

XenDesktop Machines that have not been logged in to in the past XX days

This is for statically assigned VMs or PvD XD VMs, but it outputs nice human readable user names – requires AD PowerShell Snapin.
Get-BrokerDesktop -MaxRecordCount 2000 | Where {((Get-Date) - $_.LastConnectionTime).Days -gt 60} | sort LastConnectionTime | Select DNSName,LastConnectionTime,@{Name="UserName";Expression={$UserN = $_.AssociatedUserNames.Replace("YOURDOMAINHERE\",""); $UserObj = Get-ADUser -Filter {Name -eq $UserN}; "$($UserObj.GivenName) $($UserObj.Surname)"}}

One-liner to get a listing of all users that have not logged into their XD desktop in 60 days or more – this is for static desktops or XD PvD.


  • XenDesktop PowerShell SDK (studio commandlets)
  • AD Powershell commandlets
asnp Citrix*
Get-BrokerDesktop -MaxRecordCount 2000 | Where {((Get-Date) - $_.LastConnectionTime).Days -gt 60} | sort LastConnectionTime | Select DNSName,LastConnectionTime,@{Name="UserName";Expression={$UserN = $_.AssociatedUserFullNames.Replace("DOMAINHERE\",""); $UserObj = Get-ADUser -Filter {Name -eq $UserN}; "$($UserObj.GivenName) $($UserObj.Surname)"}}


  • Use MaxRecordCount for large environments
  • Replace “DOMAINHERE\” with your domain

Updating MDT OS Images with WSUS

# WIM offline updater
# Inspired by: https://technet.microsoft.com/en-us/magazine/hh825626.aspx
# Author: Jake Rutski
# @JRutski blogs.serioustek.net
# Use at your own risk; I am not responsible for any issues caused by this script

# Variables
$imagePath = "\\storage\Software\MDT\Operating Systems\Windows Server 2012 R2\sources\install.wim"
$wsusPath = "D:\WSUS\WsusContent"
$mountPath = "C:\Mount"
$imageIndex = 4

# Check for root
# http://blogs.technet.com/b/heyscriptingguy/archive/2011/05/11/check-for-admin-credentials-in-a-powershell-script.aspx
If(!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
Write-Host "`nThis script is not running as administrator - this is required to use DISM`n"
# Mount the image
Mount-WindowsImage -ImagePath $imagePath -Path $mountPath -Index $imageIndex

# Get the update files and install them offline
foreach($cabFile in (gci $wsusPath -Filter *.cab -Recurse))
Add-WindowsPackage -PackagePath $cabFile.FullName -Path C:\Mount

# Dismount and save the image
Dismount-WindowsImage -Path C:\Mount -Save

Cleaning up Static XenDesktop VMs (including PowerCLI)

These series of cmdlets will remove the desktop from the delivery group and machine catalog, remove the object from AD, and delete the VM from vCenter. Replace ‘Domain\ComputerName’ with the appropriate strings; if you are not running on the DDC or not already pointed at it, make sure to add the ‘adminaddress’ parameter. *Note: these commands remove and delete things, so BE CAREFUL!

$XDesktop = Get-BrokerMachine -MachineName Domain\ComputerName
$XDesktop | Set-BrokerMachineMaintenanceMode -MaintenanceMode $True
Stop-BrokerSession (Get-BrokerDesktop -DNSName machinename.domain.com).SessionUid
New-BrokerHostingPowerAction -MachineName Domain\ComputerName -Action shutdown
$XDesktop | Remove-BrokerMachine -DesktopGroup GroupUID -Force
$XDesktop | Remove-BrokerMachine -Force
Remove-ADComputer ComputerName
Get-VM VMName | Remove-VM -DeleteFromDisk

Creating a single text file from multiple files

This one-liner takes all text files in a directory and appends them all to a single new file.

Get-Content "C:\Test\Files\*.txt" -Force | Set-Content "C:\Test\Files\newFile.txt"

Copying all users in one AD group to another AD group

Simple one-liner to copy users from one group to another – requires AD Powershell plugins.

Get-ADGroupMember NameOfSourceGroup | % {Add-ADGroupMember NameOfDestinationGroup -Members $_}

Output all DFSN Targets from a common root

*Requires DFS tools

Get-DfsnFolder -Path "\\kayescholer.com\files\*" | % {Get-DfsnFolderTarget -Path $_.Path | Select Path,NamespacePath,State,TargetPath,ReferralPriorityClass}

Basic IPMI Commands

Works on SuperMicro BMC IPMI on X9\X10 boards

$creds = Get-Credential
# To start the server
Get-PcsvDevice -TargetAddress your.ip.address.here -ManagementProtocol IPMI -Credential $creds | Start-PcsvDevice

# To stop the server
Get-PcsvDevice -TargetAddress your.ip.address.here -ManagementProtocol IPMI -Credential $creds | Stop-PcsvDevice


Leave a Reply