Adding a Published Application to multiple Delivery Groups in XenDesktop 7.x

Although assigning a Published Application to multiple Worker Groups in XenApp 6.x was a fairly straightforward task, the same activity is not as intuitive in XenDesktop 7.x. The Citrix Product Documentation isn’t exactly crystal clear on the process either. As such, I thought I would take the opportunity to document the process here.

Firstly, I am using XenDesktop 7.1 in my example below and I haven’t found a way to do this using the GUI, so we have to use PowerShell. I haven’t validated this for 7.0 or 7.5, although I assume the process will be the same.

After creating the target Delivery Groups, the first thing to do is discover and publish the required application(s) to the first Delivery Group using the Citrix Studio Console. I suggest using this method as it is quick and easy. Alternatively PowerShell can be used to create the application. I will detail at the end of the article.

Once you have a Published Application you will need to launch PowerShell, again I find this easiest to do from the Citrix Studio Console. The following command will assign the named Published Application to the Delivery Group specified, much like you would do with XenApp 6.x and Worker Groups. This can be repeated as required.

Note: Published Applications can only be assigned to Delivery Group with a type of ‘Applications Only’ or ‘Desktops and Applications’

Add-BrokerApplication -Name "Publised App Name" -DesktopGroup "Delivery Group 1"

In addition to this a priority can also be assigned. By default the priority is 0. 0 is the highest priority. To assign a priority, use the -priority attribute as seen below. The priority can be used to either load balance the group, when both Delivery Groups have the same priority, or in failover order as the priority descends.

Add-BrokerApplication -Name "Publised App Name" -DesktopGroup "Delivery Group 1" -priority 1

To add a Published Application using PowerShell use the following Cmdlet:

Add-BrokerApplication -BrowserName "Publised App Name" -DesktopGroup "Delivery Group 1"

I hope this helps.

Automating COM+ Applications Management Using VBScript

I wanted a script to add the Network Service account to all available roles for a specific COM+ application, however, it seems to be really hard to find out how to script these actions. Anyway after some research here is a sample script to assign the Network Service account in this case to all roles within the Sample COM+ application.

'' Setup variables
Const ApplicationName = "Sample"
Const AccountName = "NT AUTHORITY\NETWORK SERVICE"

'' Setup COM+ Application Catalog Object
Set Catalog = CreateObject("COMAdmin.COMAdminCatalog")
Set apps = Catalog.GetCollection("Applications")
''Populate the object with Applications from the COM Admin Catalog object
apps.populate

'' Loop for each application in the array
For each app in apps
'' Check for my application
    If app.Name = ApplicationName then
    '' If the application is found perform actions then create the roles object
        '' Clear the application Authentication Access Checks value
        app.Value("ApplicationAccessChecksEnabled") = false
        '' Set the application identity to be the Network Service
        app.Value("Identity") = "NT AUTHORITY\NetworkService"
        '' Save the changes to the application object
        apps.SaveChanges
        Set roles = apps.GetCollection("Roles", app.key)
        '' Populate the roles array with the roles from the current application in the initial loop
        roles.populate
        '' Loop each role in the roles array
        For each role in roles
            '' Setup the users array by getting the UsersInRole attribute
            Set users = roles.GetCollection("UsersInRole", role.Key)
            '' Add a new element in the array for the new user
            Set user = users.Add
            '' Set the user to add as the AccountName variable
            user.Value("User") = AccountName
            '' Save the changes to the array back to the COM+ Application
            users.SaveChanges
        '' Progress the roles loop
        Next
    '' Escape the If statment
    End If
'' Progress the application loop
Next

There is a useful MDSN article outlining all the avaliable object properties here

Hopefully this helps you automate your own COM+ Application administration.

Checking for VM Snapshots in vCenter using Powershell

A small script to output snapshots per VM.

Connect-VIServer myserver.fqdn.com
Write "#####START#####"
$vms = $null
$vms = Get-VM
foreach ($vm in $vms) {
$snapshots =  Get-Snapshot -VM $vm
$i = 1
foreach ($snapshot in $snapshots) {
$i = $i + 1
if ($i -ge 2) {
$vm.name
$i
#$snapshot.Name
#$snapshotTable =  @($vm.Name) # | Sort-Object {$_.name}
#$snapshotTable
}
}
}
Write "#####DONE######"

You can also list snapshots based on a name containing any value using the following code:

Get-VM | Get-Snapshot | Where-Object {$_. -contains "searchString"}

How to add datastores to single host in vCenter using Powershell

Connect-VIServer myserver.fqdn.com 
$VMHost = (Read-Host "Please enter the name of your the ESX Host you wish to configure")

$shellObject = new-object -comobject wscript.shell 
$intAnswer = $shellObject.popup("Do you want to add the datastores?", 0,"Add datastores - remember you must have added the hosts on the storage",4) 
If ($intAnswer -eq 6) {
Write "Creating Datastores on $VMHost…" 
New-Datastore -Nfs -VMHost $VMHost -Name datastorename -Path /vol/volname -NfsHost 10.10.10.10
New-Datastore -Nfs -VMHost $VMHost -Name datastorename -Path /vol/volname -NfsHost 10.10.10.10
} else {
Write "Skipping Datastores on $VMHost…" 
} 

List all VMs with a memory limit set in vCenter using Powershell

This script lists all VMs with a memory limit set in Resource Manger in a given VMWare cluster.

Connect-VIServer myserver.fqdn.com 
Get-Cluster $Cluster | Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne "-1"}

If you want to clear all memory limits and set them to unlimited use the following code

Connect-VIServer myserver.fqdn.com 
Get-Cluster MyCluster | Get-VM | Get-VMResourceConfiguration | where {$_.MemLimitMB -ne "-1"} | Set-VMResourceConfiguration -MemLimitMB $null

The same can also be done for the CPU management using CpuLimitMhz attribute.

Repurposed PCs and Citrix Desktop Appliance

Citrix Desktop Appliance is a great hidden secret of Web Interface and can easily be used as an alternate approach to a thin client deployment.

The Desktop Appliance is a cut down version of a standard Web Interface site. Once logged on the site takes the user directly to their desktop, this can be a XenApp published desktop and XenDesktop VDA. When installing the Web Interface component to the XenDesktop Delivery Controller the Desktop Appliance site is automatically created.

To deploy the site to an existing instance of the Web Interface I followed this blog.

Create a Desktop Appliance Web Interface Site
The appliance mode site is actually an additional website that gets hosted alongside the standard Web Interface site. The appliance site is created by default when deploying Web Interface for XenDesktop and can be easily added for XenApp. Creating an appliance mode site will not have any impact on existing web interface sites (unless you overlap the URLs).

There is no option for creating or configuring an appliance mode site in the current version of the Citrix Web Interface Management Console. No worries, it’s very simple to do using the Citrix sitemgr tool and a good opportunity to get down and dirty with your web interface site config.

Creating the appliance site:

■Navigate to: c:\Program Files (x86)\Citrix\Web Interface\5.3.0.
■Run command:
sitemgr -c DACDest=1:/Citrix/DesktopAppliance,XMLService=XAServer:XmlSvcPort
■Confirm the site was created by accessing it at the newly created URL or by checking for the deployment of site files at c:\inetpub\wwwroot\citrix\DesktopAppliance.
Configuring a single domain login:
If all users accessing the appliance site will authenticate using the same domain, the domain field can be hidden to simplify and clean up the login.

■Edit the file “c:\inetpub\wwwroot\citrix\DesktopAppliance\conf\webinterface.conf” as follows:
■Uncomment “DomainSelection” and set it to “”
■Uncomment “HideDomainField” and verify it is set to “On”
■Uncomment “LoginDomains” and set it to “”
■Uncomment “RestrictDomains” and verify it is set to “On”

To specify multiple XML servers you can use a semi-colon ; to separate the server entry’s.

How does this work with multiple desktops?
Well it’s quite simple the site connects the user directly to the first desktop in alphabetical order.

But I have multiple desktops and want to prioritise the desktop order?
Fear not, this can be achieved by editing the published desktop name.
desktop.jpg
Note: Not the display name that users see.

The next step of this and my real aim was to repurpose fat (old) PCs as thin clients. This approach saves on the upfront costs associated with a typical thin client rollout and additionally you get to take advantage of great HDX features such a HDX Media Stream or HDX Rich Graphics with RemoteFX. So I wanted a quick low touch approach that didn’t involve spending money, this somewhat limited the options and this is what I came up with.

A simple VB script combining a few different techniques. The things I wanted to consider:

  • Users should only logon once
  • The environment must be relatively locked down
  • The user experience should be seamless

So I combined a few scripts from around the web (Sources below) to come up with this:

'' Repurpose PC

''Create local user
strComputer = "localhost"
Set colAccounts = GetObject("WinNT://" & strComputer & "")
Set objUser = colAccounts.Create("user","Citrix")
objUser.SetPassword "MyPassword"
objUser.SetInfo

''
'Declarations'
''
Dim objShell
Dim RegLocAutoLogon
Dim keyDefaultDomainName
Dim valDefaultDomainName
Dim keyDefaultUserName
Dim valDefaultUserName
Dim keyDisableCAD
Dim valDisableCAD
Dim keyAutoAdminLogon
Dim valAutoAdminLogon
Dim keyForceAutoLogon
Dim valForceAutoLogon
Dim keyDefaultPassword
Dim valDefaultPassword
'''
'Define keys and values'
'''
RegLocAutoLogon = "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Winlogon\"
keyDefaultDomainName = "DefaultDomainName"
valDefaultDomainName = ""
keyDefaultUserName = "DefaultUserName"
valDefaultUserName = "Citrix"
keyDisableCAD = "DisableCAD"
valDisableCAD = 1
keyAutoAdminLogon = "AutoAdminLogon"
valAutoAdminLogon = "1"
keyForceAutoLogon = "ForceAutoLogon"
valForceAutoLogon = "1"
keyDefaultPassword = "DefaultPassword"
valDefaultPassword = "MyPassword"
keyShell = "Shell"
keyShellValue = """C:\Program Files\Internet Explorer\iexplore.exe"" -k http://myhost.mydomain.com/citrix/desktopappliance"
Set objShell = CreateObject("WScript.Shell")

''Begin setting the autologon registry keys
objShell.RegWrite RegLocAutoLogon & keyDefaultDomainName, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultDomainName, valDefaultDomainName, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultUserName, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultUserName, valDefaultUserName, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDisableCAD, 1, "REG_DWORD"
objShell.RegWrite RegLocAutoLogon & keyDisableCAD, valDisableCAD, "REG_DWORD"
objShell.RegWrite RegLocAutoLogon & keyAutoAdminLogon, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyAutoAdminLogon, valAutoAdminLogon, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyForceAutoLogon, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyForceAutoLogon, valForceAutoLogon, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultPassword, 1, "REG_SZ"
objShell.RegWrite RegLocAutoLogon & keyDefaultPassword, valDefaultPassword, "REG_SZ"

''Set the machine shell to be the desktop appliance
objShell.RegWrite RegLocAutoLogon & keyShell , keyShellValue , "REG_SZ"

''Give feedback to the admin
WScript.Echo "Done PC converted"

This code in a nut shell creates a local user, sets up auto logon for Windows using the newly created local user and then sets the Windows default shell to be an Internet Explorer kiosk mode window.
Things to keep in mind:

  • Admins have to hold shift before the logon process starts to override the auto logon
  • Admins have to run task manager to start explorer.exe as the shell in this example
  • Task manager is still available to users. This could be locked down by local machine policy, group policy or a product such as AppSense
  • The machine is still running Windows and as a result would still need to be patched and manage although hardening the install maybe appropriate

Despite some of the draw backs I still firmly believe this approach is a great on ramp to thin client deployment leveraging some of the HDX and web interface components within the Citrix product suite that often go unused.

Sources:

Citrix Blogs
Microsoft MSDN
Microsoft Technet
Tek-tips forum

Bulk add a VMNetwork to a ESX Cluster

A quick powershell script to add a new VM Network to an existing ESX Cluster.

Connect-VIServer vsphere.example.com 
$Cluster = (Read-Host "Enter cluster name")
$vSwitch = (Read-Host "Enter vSwitch to add the port group to")
$PortGroup = (Read-Host "Enter vmNetwork name")
$vLANPortGroup = (Read-Host "Enter vmNetwork vLAN number")
Get-Cluster $Cluster | Get-VMHost -State "Connected" | Get-VirtualSwitch -Name $vSwitch | New-VirtualPortGroup -Name $PortGroup -VLanId $vLANPortGroup