Instantly Publishing Citrix Apps to Individual Servers Using PowerShell

Sometimes there is a need to publish an application to individual XenApp servers for baselining or troubleshooting purposes. But if you have a lot of published applications in your XenApp 6 farm, this can be a huge hassle. Thankfully PowerShell allows us to quickly and easily take our existing published applications and automatically create individually published apps for each server. We can use Worker Groups to control which servers get an individually published application. Not only that, we can organize the applications neatly by creating separate console and Client folders for each server. I wrote this script to accomplish all of the above using XenApp 6 PowerShell SDK’s powerful features:

$appFolder = "Applications"
$testfolderpath =  "Applications/Test/Single Server Test"
$sourceAppPath = "Applications/Test"	#apps in the root of this path will not be copied
$publishTo = "DOMAIN\GroupWithAccessToIndividualServers"
$targetWorkerGroup = "Main Farm Servers"
$clientFolder = "Test\Single Server Test"
$WhatIfPreference = $false		# Simulate script but do not execute any changes (will yield errors)

# Main Program

$servers = Get-XAServer -workergroupname $targetWorkerGroup
$sourceFolders = Get-XAFolder -folderpath $appFolder -recurse | where {$_ -notmatch $testfolderpath -and $_ -match $sourceAppPath -and $_ -ne $sourceAppPath}

# Create folder for each server
foreach ($server in $servers) {						
	#generate folder name for each server
	$createfolder = $testfolderpath+"/"+$server.servername
	#create folder for each server
	new-xafolder -folderpath $createfolder
	foreach ($folder in $sourceFolders) {
		#get list of apps to copy in each folder
		$appstocopy = Get-XAApplication -folderpath $folder			
		foreach ($app in $appstocopy) {
			## generate name for new app
			$newname = $app.displayname+" "+$server.servername
			$newclientfolder = $clientfolder+"\"+$server.servername
			## get existing accounts to remove			
			$accountsToRemove = ($app | Get-XAApplicationReport).accounts
			## copy application to server's folder		
			$newapp = $app | Copy-XAApplication -folderpath $createfolder
			## publish application to lone server		
			$newapp | set-xaapplication -servernames $server.servername -clientFolder $newclientFolder
			## remove existing accounts
			foreach ($account in $accountsToRemove) {
				$newapp | remove-xaapplicationaccount -Accounts $account
			## publish application to AD group
			$newapp | add-xaapplicationaccount -Accounts $publishTo
			## rename new application
			$newapp | rename-xaapplication -newdisplayname $newname						

Download the script from GitHub.

Just set the variables with what is appropriate for your environment and run the script.
The $appFolder variable is the root path of your applications (default is “Applications”)
$testfolderpath is the full path of the folder where the applications published to individual servers will be published (no trailing slash)
Set $sourceAppPath one level higher than the path of the folder containing the applications you wish to copy. The script will recurse down into child folders from this path, but will not copy applications that reside within this path.
$publishTo is a string containing the AD users or groups the newly published applications should be published to
$targetWorkerGroup is the name of the worker group containing the servers the applications will be published to
$clientFolder is the root Program Neighborhood/Client folder that the individual server folders will be created under

The once-daunting and time-consuming task of copying and modifying applications for each server can now be done automatically in a matter of minutes!

Update: It’s even easier to undo the changes made by the above script if you decide you want to scrap the newly published apps and folders and start over. Just use the following script:

$testfolderpath =  "Applications/Test/Single Server Test"
$WhatIfPreference = $false

# Main Program
(get-xaapplication -folderpath (Get-XAFolder -folderpath $testfolderpath)) | remove-xaapplication
(get-xafolder -folderpath $testfolderpath) | remove-xafolder