Sep 302016


XenApp 7.6

700+ Delivered (published) Applications

60+ Windows servers (2008 R2 and 2012 R2)



Recently I had a request to replicate 100+ applications from PROD to QA, using QA server configured with identical applications and identical application locations/paths. Obviously all paths to EXE files need to be the same in order for this to work 100% (unless I missed a memo and XA can now support publishing of identical applications from various paths.  As far as I know, this was not yet available in 7.6).  If QA server has some of the applications in different paths, not all is lost. You can still use this process and script to migrate large number of applications between delivery groups and then modify paths later in Studio.

While I could add few more lines to my PoSH script to actually replicate each application at a time, amount of time it took me to create this script and ability to duplicate applications in Studio seemed unnecessary.

My goal was to replicate, or proper Citrix term would be duplicate all applications and then assign them to another delivery group. Seems simple enough for Citrix and PoSH guru. But for those who are just getting their feet wet could use following process to speed up their delivery time to less than 5 mins and go look for the end of the Internet, while telling client it took you hours 😉



1 – I will be duplicating all requested applications using ol’ Citix Studio.

2 – I will run script below to change Delivery Group and application folder, as visible by the user (you mileage might vary, depending on your requirements)

This script/process is no rocket science, but might help someone to quickly replicate applications and migrate them to another delivery group, instead of publishing them over again.  Modify script below according to your environment before running it.  (WARNING: It is fairly simple script, so review and try to understand exactly what this script is doing, before executing it.)  Also, I am no expert when it comes to creating powershell scripts, but just another Citrix admin.  So, pardon if you can make it better.  Please do improve and share!  I am all for helping fellow Citrix admins anyway I can.  Even if it’s buying a pint!


Step 1

citrixirc1Create alternative application folder in Studio.  For our scenario I am going to create folder named “QA” inside already created “Europe” folder.

Right-click on all applications that you need to replicate in QA (you can select multiple applications at once).

Click Duplicate Application 

Now select all duplicates and drag them over to QA folder.  In my scenario I will be dragging these to Europe\QA.

Step 2

Below script will prompt for the admin folder name where all the duplicates reside (that’s the new folder you just created.  In my example it’s called Europe\QA).  I repeat- do not select your production applications folder, as script will move all your production apps to new delivery group.  Use newly created QA folder where you moved all duplicate applications to in step 1 above.

It is assumed that new delivery group is already created.

Another item to note; there is an optional line (in yellow) to change client-side folder location of newly created applications.  This is to help users identify whether they are running PROD or QA applications. It also looks cleaner in Storefront or WI.  You can add more commands into Foreach loop.  Things like modifying users who have access, or changing actual name of the application and etc.  My goal was to keep all the same and just deliver from QA server.


asnp Citrix*

$adminfolder = (Get-BrokerApplication -MaxRecordCount 10000).AdminFolderName | sort | select -unique | Out-GridView -Title "Select Admin Folder Name" -OutputMode Single
$applist = Get-Brokerapplication -AdminFolderName $adminfolder
$originalDG = (Get-BrokerDesktopGroup -MaxRecordCount 10000).Name | sort | Out-GridView -Title "Select Original Delivery Group Name" -OutputMode Single
$newDG = (Get-BrokerDesktopGroup -MaxRecordCount 10000).Name | sort | Out-GridView -Title "Select New Delivery Group Name" -OutputMode Single

Write-Host "Migrating all applications in $adminfolder`nFrom $originalDG Delivery Group to $newDG Delivery Group" -ForegroundColor Green

foreach ($app in $applist.ApplicationName){
                Write-host "Migrating $app"
                Get-BrokerApplication -ApplicationName $app | Add-BrokerApplication -DesktopGroup $newDG
                Get-BrokerApplication -ApplicationName $app | Remove-BrokerApplication -DesktopGroup $originalDG
                Get-BrokerApplication -ApplicationName $app | Set-BrokerApplication -ClientFolder "Europe\QA" #optional to show all applications inside QA folder and not in the same folder with production apps


BTW, using similar add-brokerapplication command you can publish, or rather deliver same application from multiple delivery groups.  Just comment out remove-brokerapplication command and it will now launch from servers in prod and qa, or any other DG of your choice.  Comes really handy when you have multiple DGs that host different applications, but some of the applications are identical.  You can spread the load across multiple DGs.  Think of it as a worker groups concept in XA 6.x with server groups.   I had such requirement that was easily achievable in XA 6.x, but not so much in XA 7.x.  I paid for someone’s case of beer when they told me that I can use above mentioned command to deliver same application from multiple DG’s, as it’s not clearly documented by Citrix. There is a surprise…

That’s all folks. My first ever citrixirc blog.  Whoo-hoo!

Over and out.

Feb 242016

Have you ever looked at director and saw a user had a very long login, and wondered how the hell you could find out who that was?  I wrote a script to help you out a bit!

Here is the script

Read it!  There are places you will have to edit to allow it to run in your environment.  Search for ##### to find the spots to pay attention to.

In the end it will output a .htm file to your my documents\logon_logs and open after it finishes.


Note: I have no idea if this works for XA, but I know it works for XD 7.6

Aug 062014

Post credit goes to David62277, a community contributor from #Citrix IRC on Freenode In order to update certain software on a PVS image (hosting platform tools, pvs target device software, etc) it is required to “reverse image” your vdisk back to a normal VM, install your update, and image back to vdisk. This is because the machine is actually booted to network (it is getting its C: drive from a network share essentially), and if you disrupt that connection while the vdisk is in private mode it can (most likely will) ruin your vdisk image. The process of reverse imaging, and re-imaging your vdisk can be very time consuming. There is a better way… update your vDisk without having to reverse image by directly booting to a .VHD from Windows PE.

You will need the Microsoft Windows AIK (I’m using Windows 7 version)


  1. Download and install the Microsoft Windows AIK and install it on your workstation
    1. This is what we will use to create a bootable .iso image
  2. Once installed create your .iso
    1. Start => All Programs => Microsoft Windows AIK => Deployment Tools Command Prompt1-BootVHDwithPE
    2. Run “copype.cmd amd64 c:\winpe” (note: you can use x86 or ia64 depending on your architecture… don’t think it matters though. Also, you can specify a different directory).2-BootVHDwithPE.png
    3. Now we want to add boot support
      1. Imagex /apply c:\winpe\winpe.wim 1 c:\winpe\mount
      2. Copy c:\winpe\iso\bootmgr c:\winpe\mount
      3. Mkdir c:\winpe\mount\boot3-BootVHDwithPE.png
    4. Run the following commands:
      1. Bcdedit /createstore c:\winpe\mount\boot\BCD
      2. Bcdedit /store c:\winpe\mount\boot\BCD -create {bootmgr} /d “Boot Manager”
      3. Bcdedit /store c:\winpe\mount\boot\BCD -set {bootmgr} device boot
      4. Bcdedit /store c:\winpe\mount\boot\BCD -create /d “WINPE” -application osloader4-BootVHDwithPE
    5. Run the following commands using the guid you received from the last command
      1. Bcdedit /store c:\winpe\mount\boot\BCD -set <GUID> osdevice boot
      2. Bcdedit /store c:\winpe\mount\boot\BCD -set <GUID> device boot
      3. Bcdedit /store c:\winpe\mount\boot\BCD -set <GUID> path \windows\system32\winload.exe
      4. Bcdedit /store c:\winpe\mount\boot\BCD -set <GUID> systemroot \windows
      5. Bcdedit /store c:\winpe\mount\boot\BCD -set <GUID> winpe yes
      6. Bcdedit /store c:\winpe\mount\boot\BCD -set <GUID> detecthal yes
      7. Bcdedit /store c:\winpe\mount\boot\BCD -displayorder <GUID> -addlast5-BootVHDwithPE
    6. One last command
      1. Oscdimg -n -m -o -bc:\winpe\ c:\winpe\mount c:\winpe\bootdisk.iso6-BootVHDwithPE
    7. Done with the “hard” part
  3. Copy the .iso file to your ISO storage repository (xenserver, vmware, whatever)
  4. Create a new disk in your hypervisor that is about 2x as large as the size of your vdisk (note: use the size it shows in the PVS console x 2) – this gives you room to play.
  5. Attach that disk to your PVS server
    1. Create a partition, format, etc.
  6. Merge your vdisk to a new merged base (set it as test)7-BootVHDwithPE
  7. Copy the merged .vhd file to the new drive you just attached to the PVS server
  8. Detach the new drive from the pvs server, and attach it to the VM you normally use to update your image (should be the only drive attached), or a VM that matches the virtual hardware of your target devices.
    1. If the vm is a target device in PVS set it to boot from hard disk not vdisk
  9. If using Xenserver set the VM to boot from CD, if using vmware edit settings of the vm to boot into bios so you can change the boot order so CD is first.
  10. Boot the VM and you should see this screen8-BootVHDwithPE
  11. Run the following commands
    1. Diskpart
    2. List disk
      1. Should see disk 0 and only9-BootVHDwithPE
    3. Select disk 0
    4. Select part 1
    5. Active
      1. This makes partition 1 on disk 0 bootable10-BootVHDwithPE
    6. exit
    7. Now I want to rename the .vhd file on disk 0 (C:\), so I can use it over and over again (NOTE: this is CASE SENSITIVE)
    8. C:
    9. Dir
      1. Just so I can see the file name
    10. Ren win8.8.vhd temp.vhd (or whatever you want to name it. NOTE: this is CASE SENSITIVE)11-BootVHDwithPE
    11. X:
    12. Diskpart
    13. Select vdisk file=c:\temp.vhd
    14. Attach vdisk
    15. List vol
  12. Now I can see my vhd is mounted as volume D (yours may be different, but make note of it)
  13. A couple more commands
    1. Exit (to exit diskpart)
    2. Bcdboot d:\windows /s c:
      1. Use whatever volume letter you have for your vdisk13-BootVHDwithPE
    3. Exit
      1. System should now reboot and boot into your vhd (just remember not to hit any key, or just eject the cd image from the vm)
  14. Make the changes that normally would require you to reverse image, and shut down.
  15. Detach the drive from the editing VM and re-attach it to your PVS server.
  16. Copy the .vhd back to the store
  17. Detach the drive (keep it around for next time)
  18. Rename the original vhd (win8.8.vhd for me) to .old, and rename the temp.vhd to whatever the original name was. (NOTE: this is CASE SENSITIVE)
  19. Boot your test devices and make sure everything is working
  20. Once satisfied, shutdown the test devices, delete the .old file, and promote the vdisk to production
  21. Switch the editing VM back to booting from network for when you have your normal updates

From here on out these kinds of edits should be easy.

  1. Attach the virtual disk to pvs
  2. Remove the old temp.vhd file (assuming you didn’t before)
  3. Copy the vhd you wish to edit to it
  4. Rename it to temp.vhd (or whatever you named it to begin with)
  5. Detach the drive from PVS
  6. Change your editing vm target device in PVS to boot to hard drive
  7. Attach the drive to your editing vm
  8. Boot it
  9. Follow steps 14-20 above
Apr 042014

Often when troubleshooting an issue a need arises to collect logs from multiple machines.  This is easily achieved when the number of machines is small, or known – a few servers or desktops here or there – but when it comes to analyzing logs for a large pooled-random group of desktops or several hundred computers in your organization, grabbing the files can be a pain.  Using the magic of Powershell, you can easily collect logs from as many computers as you desire in a matter of minutes.

Add-PSSnapin Citrix*
$DeliveryController = "citrixdc.contoso.local"
$vmCollection = Get-BrokerDesktop -PowerState On -AdminAddress $DeliveryController -MaxRecordCount 9999
# you can replace or repeat this with any collection you want (i.e. get-adcomputer).

foreach($hostedDesktop in $vmCollection)
$vm = $_.DNSName
if(Test-Connection -Cn $vm -BufferSize 16 -Count 1 -ea 0 -quiet)
Write-Host "$vm is online, collecting logs"
$path="\\$vm\d$\" #Use your log location. In this case, logs are co-located logs on the write cache D: drive.
dir -Path $path -recurse -include "*.evtx","*.log" -Exclude "*vdiskcache","pagefile.sys" | %{ # Critera shown for example. If you include all, be sure you exclude vdiskcache and pagefile.sys
$destPath="$destbasePath\$vm" # The full destination path
if(!(test-path $destPath)) { mkdir $destPath } #make new folders for each VM you collect from
copy $_.pspath $destPath #Make the magic happen