<# This script will sync published apps from a Delivery Group in a Site to a Delivery Group in another Site. Note that this script does not handle file type associations at this point. References: - https://www.sepago.de/blog/export-and-import-citrix-xendesktop-published-apps/ - https://xdreplicate.readthedocs.io/en/latest/ - https://github.com/ryancbutler/XDReplicate Script name: Sync-PublishedApplications.ps1 Release 1.4 Written by Jeremy Saunders (jeremy@jhouseconsulting.com) 27th February 2017 Modified by Jeremy Saunders (jeremy@jhouseconsulting.com) 12th February 2021 #> #------------------------------------------------------------- # Set Powershell Compatibility Mode Set-StrictMode -Version 2.0 # Enable verbose, warning and error mode $VerbosePreference = 'Continue' $WarningPreference = 'Continue' $ErrorPreference = 'Continue' #------------------------------------------------------------- # Set these variables # Source Site and Deliver Group # Set the Source Site Admin folder $SourceAdminFolder = "TCE-Perth\QA\" # Set the Source Site Client folder $SourceClientFolder = "TCE Perth\QA" # Set the Source Site Deliver Group $SourceDG = "DG-PER-Win2016-QA01" # Set the Source Site Delivery Controller $SourceDeliveryController = "per1cxd01.jhouseconsulting.com.au" # Set the Destination Site Admin folder $DestinationAdminFolder = "TCE-Perth\QA\" # Set the Destination Site Client folder $DestinationClientFolder = "TCE Perth\QA" # Set the Destination Site Deliver Group $DestinationDG = "DG-PER-Win2016-QA01" # Set the Destination Site Delivery Controller $DestinationDeliveryController = "per2cxd01.jhouseconsulting.com.au" # Set the Destination Site Users/Groups you want to publish the apps to. Set an empty array @() to disable app filtering. $PublishToExistingUsers = $True $PublishToUsers = @() #------------------------------------------------------------- Add-PSSnapin citrix* # The Test-BrokerAdminFolder and new-adminfolders functions are taken from Ryan Butler's XDReplicate script function Test-BrokerAdminFolder { <# .SYNOPSIS Tests if administrative folder exists .DESCRIPTION Checks for administrative folder and returns bool .PARAMETER FOLDER Folder to validate .PARAMETER XDHOST XenDesktop DDC hostname to connect to #> Param( [Parameter(Mandatory=$true)][string]$folder, [Parameter(Mandatory=$true)][string]$xdhost) write-host "Processing Folder $folder" -ForegroundColor Magenta #Doesn't follow normal error handling so can't use try\catch Get-BrokerAdminFolder -AdminAddress $xdhost -name $folder -ErrorVariable myerror -ErrorAction SilentlyContinue if ($myerror -like "Object does not exist") { write-host "FOLDER NOT FOUND" -ForegroundColor YELLOW $found = $false } else { write-host "FOLDER FOUND" -ForegroundColor GREEN $found = $true } return $found } function new-adminfolders { <# .SYNOPSIS Creates new administrative folder .DESCRIPTION Checks for and creates administrative folder if not found .PARAMETER FOLDER Folder to validate .PARAMETER XDHOST XenDesktop DDC hostname to connect to #> Param( [Parameter(Mandatory=$true)][string]$folder, [Parameter(Mandatory=$true)][string]$xdhost ) $paths = @($folder -split "\\"|where-object{$_ -ne ""}) $lastfolder = $null for($d=0; $d -le ($paths.Count -1); $d++) { if($d -eq 0) { if((Test-BrokerAdminFolder -folder ($paths[$d] + "\") -xdhost $xdhost) -eq $false) { New-BrokerAdminFolder -AdminAddress $xdhost -FolderName $paths[$d]|Out-Null } $lastfolder = $paths[$d] } else { if((Test-BrokerAdminFolder -folder ($lastfolder + "\" + $paths[$d] + "\") -xdhost $xdhost) -eq $false) { New-BrokerAdminFolder -AdminAddress $xdhost -FolderName $paths[$d] -ParentFolder $lastfolder|Out-Null } $lastfolder = $lastfolder + "\" + $paths[$d] } } } #Get-BrokerDesktopGroup -AdminAddress $SourceDeliveryController -Name $SourceDG $SourceDeliveryGroupUUID = (Get-BrokerDesktopGroup -AdminAddress $SourceDeliveryController -Name $SourceDG).UUID | Select -ExpandProperty Guid $SourceDeliveryGroupUUID # Get the apps from the Source Site $SourceApps = Get-BrokerApplication -AdminAddress $SourceDeliveryController -AdminFolderName $SourceAdminFolder -MaxRecordCount 9999 | where {$_.AssociatedDesktopGroupUUIDs -contains $SourceDeliveryGroupUUID -AND $_.ClientFolder -like "*$SourceClientFolder*" } #$SourceApps # Create Admin Folder on Destination Site if it does not exist. new-adminfolders $DestinationAdminFolder $DestinationDeliveryController # Create the apps in the Destination Site and publish to the specified users ForEach ($App in $SourceApps) { If ($PublishToExistingUsers) { $AppUserFilterEnabled = $App.Enabled $PublishToUsers = $App.associatedUsernames } Else { If (($PublishToUsers | Measure-Object).Count -eq 0) { $AppUserFilterEnabled = $False } Else { $AppUserFilterEnabled = $True } } # Get the Icons from the Source Site and create them in the Destination Site $SourceIcon = Get-BrokerIcon -AdminAddress $SourceDeliveryController -Uid ($app.IconUid) $DestinationIcon = New-BrokerIcon -AdminAddress $DestinationDeliveryController -EncodedIconData $SourceIcon.EncodedIconData write-verbose "Creating new app: $($app.ApplicationName)" -verbose For ($i = 0; $i -lt 5; $i++) { $Success = $False Try { If ($i -gt 0) { New-BrokerApplication -AdminAddress $DestinationDeliveryController -ApplicationType "HostedOnDesktop" -CommandLineExecutable "$($app.CommandLineExecutable)" -AdminFolder "$DestinationAdminFolder" -ClientFolder "$($app.ClientFolder)" -CommandLineArguments "$($app.CommandLineArguments)" -Enabled $app.Enabled -Name "$($app.applicationName)" -UserFilterEnabled $AppUserFilterEnabled -WorkingDirectory "$($app.WorkingDirectory)" -PublishedName "$($app.PublishedName)" -DesktopGroup "$DestinationDG" -iconUid $DestinationIcon.Uid } Else { $NewBrowserName = $($app.PublishedName) + $i New-BrokerApplication -AdminAddress $DestinationDeliveryController -ApplicationType "HostedOnDesktop" -CommandLineExecutable "$($app.CommandLineExecutable)" -AdminFolder "$DestinationAdminFolder" -ClientFolder "$($app.ClientFolder)" -CommandLineArguments "$($app.CommandLineArguments)" -Enabled $app.Enabled -Name "$($app.applicationName)" -UserFilterEnabled $AppUserFilterEnabled -WorkingDirectory "$($app.WorkingDirectory)" -PublishedName "$($app.PublishedName)" -BrowserName "$NewBrowserName" -DesktopGroup "$DestinationDG" -iconUid $DestinationIcon.Uid } $Success = $True } Catch { If ($Error[0].Exception.Message -eq "Specified browser name is already in use") { # Loop through and increment the number on the end of the BrowserName } } If ($Success) { break } } # Add the users If (($PublishToUsers | Measure-Object).Count -gt 0) { $AppNew = Get-BrokerApplication -AdminAddress $DestinationDeliveryController -Name "$($DestinationAdminFolder + $app.ApplicationName)" -MaxRecordCount 999999 $UidNew = $AppNew.uid ForEach ($User in $PublishToUsers) { Add-BrokerUser $User -Application $UidNew } } }