Apr 032017

Original Post

The first script I wrote was from before Citrix added real powershell functionality into PVS.  This new script leverages the new powershell module.  I am not exactly sure when they first added this into PVS (if you know please comment below), but this was developed using PVS 7.12.  Pay attention to comments marked with multiple hash tags (####) – these are places you will need to edit the script to fit your enviroment.

Here is the new script

Mar 312017

In my environment I have about 300 provisioned desktops, and when I update the vDisk sometimes it can take a while (days) before all of the VMs get the latest version.  Especially, in the case of a roll back I need a good way to get all of the VMs which are on the wrong version (and are waiting for a session) to boot to the correct version.

I think powershell version 3, but since I did it with v4 I’ll say 4+
PVS powershell module installed (learn more here)
Powershell remoting enabled on your delivery controller (also need to supply the name in the script)

What the script does:

  1. Gets a list of the Collections in your PVS environment, and outputs it to out-gridview so you can select the collection you want to focus on
    1. If you hit cancel the script ends
  2. After your select the collection and hit ok it will get all of the devices in that collection which are powered on, and cannot access a maintenance/private disk image
  3. For each of the devices in that list it checks to see if they have the latest vDisk version, or if they have the correct OverRide version.
    1. If they do then it tells you the device is on the correct version, and moves on to the next device
    2. If they do not then it will pass the device name to the check function, and after moves on to the next device
      1. invokes powershell on the delivery controller to see if the VM is in use (powershell remoting required)
        1. If it is, it tells you it is in use and does nothing
        2. If it is not it will reboot the vm, and tell you

Here is the script!  Remember to test it before using it in a production environment.


May 062016

If you have tried to use Windows 10 in XenDesktop with Citrix Profile Management you have probably run into two major issues.

The Issues
The first issue is the start menu… which is now a database located at %localappdata%\TileDataLayer\Database.  At logoff when profile manager tries to copy it off it can’t due to services locking the files.  This results in the user logging on and their start menu not working.

The second issue revolves around SMB2/3.  SMB1 would close files as soon as it was done with them, but 2/3 leave them open for a little longer in case they are requested again.  This means when a user logs off and their Pooled Random desktop shuts down file locks can remain in the profile store if the shutdown process happens too fast (which it does 99% of the time).  Basically, if a user was to logoff and then try to log back on in a short period of time their logon would be greatly delayed due to the “ghost” file locks.

The Workarounds
Start Menu – This one is a bit tricky.  When a user logs off we need to stop the Tile Data model server and State Repository Service (in that order) so that profile manager can copy the start menu database off to the user store.  Here is the rub… a normal user cannot stop these services, so you can’t use a logoff script!  Here is what you do… logon as a local administrator and…

  1. Create a powershell script on the root of C:\ – name it logoff.ps1
    1. Open powershell_ise.exe as administrator and write these 2 lines in the white space at the top (if no white space hit the new button to create a new script).
      stop-service tiledatamodelsvc -force
      stop-service staterepository -force
    2. Save it as C:\logoff.ps1 (or put it where ever you want – just remember where it is)
  2. Right click the start menu – hit run – type in taskschd.msc and hit ok
  3. Right click the Task Scheduler Library node and select Create Basic Task…
  4. Name it whatever you want – I named mine logoff – hit next
  5. Select “When a specific event is logged” on the next screen and hit next
  6. Under Log: start typing “Sec”  the Security log should show up
  7. Under Source type in “Microsoft Windows security auditing” (no quotes)
  8. Event ID will be 4647 – hit next
  9. leave Start a program selected – hit next
  10. in the program/script blank C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
  11. in the add arguments blank “-executionpolicy unrestricted -file c:\logoff.ps1” (no quotes) – if you put the script somewhere else make sure you have the path correct.
  12. click next, and on the next screen check the box “Open the Properties dialog…” and hit Finish
  13. Click Change User or Group, type in “system” (no quotes) and hit ok
  14. Check “Run with highest privileges”, and hit ok

Now when a user initiates a logoff the system will stop the Tile Data model server and State Repository Service.  This will allow profile manager to copy off the start menu database.

Ghost File locks
This one is pretty easy – we just delay the shutdown with a shutdown script.  This allows the file locks to be released at shutdown.  Here is what you do… (you should still be logged on as a local administrator)

  1. Run powershell_ise.exe as administrator and type these 2 lines in the white space at the top… again if no white space hit the new button.
    stop-service brokeragent -force
    start-sleep -s 30
  2. Save it as C:\shutdown.ps1 (or where ever you want)
  3. Right click the start menu – hit run – type in gpedit.msc
  4. Under “Computer Configuration\Windows Settings\Scripts” double click on Shutdown
  5. Click the PowerShell Scripts tab
  6. Click Add – browse to the script you just created – hit ok
  7. Hit Ok again on the shutdown properties box, and close the local group policy editor

At shutdown this script will kill the brokeragent service (just in case delaying the shutdown would allow the desktop to appear “available” again), and delay the shutdown by 30 seconds.  This allows all file locks in the profile manager store to be released.

Bonus – UPM policy settings for Windows 10 (These are mine, so you may need to tweak for your environment – of course redirect all you can)

Exclusion list (registry) 
Software\Microsoft\Internet Explorer\Recovery

Exclusion list – directories
AppData\Local\Microsoft\Windows Live
AppData\Local\Microsoft\Windows Live Contacts
AppData\Local\Microsoft\Terminal Server Client
AppData\Local\Windows Live
AppData\Local\Google\Chrome\User Data\Default\Cache
AppData\Local\Microsoft\Windows\Temporary Internet Files
AppData\Roaming\Citrix\PNAgent\Icon Cache
AppData\Roaming\Macromedia\Flash Player\macromedia.com\support\flashplayer\sys
AppData\Roaming\Macromedia\Flash Player\#SharedObjects
AppData\Local\Microsoft\Internet Explorer\Recovery
AppData\Local\Microsoft\Windows Mail
AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Dropbox
AppData\Local\Downloaded Installations
AppData\Local\Cisco\Unified Communications\Jabber\CSF\Voicemail
AppData\Local\Cisco\Unified Communications\Jabber\Voicemail
AppData\Local\ATT Connect
AppData\Local\Cisco\Unified Communications\Jabber\Crash Dump
AppData\Local\Cisco\Unified Communications\Jabber\CSF\Logs
AppData\Roaming\Microsoft\Internet Explorer\UserData
AppData\Local\Microsoft\Windows\Application Shortcuts
AppData\Local\Microsoft\Group Policy
AppData\Local\Microsoft\Media Player

Exclusion list – files

Files to synchronize

Directories to synchronize

Folders to mirror

Process Internet Cookie files on logoff  – Enabled

Process logons of local administrators – Enabled

Profile streaming – Enabled

Path to user store – \\server\share\%username%.%userdomain%\!CTX_PROFILEVER!!CTX_OSBITNESS!

Enable Profile management – Enabled

One more bonus!!
Based mostly on this Citrix blog – Windows 10 Optimization for XenDesktop – I wrote a powershell script to automatically optimize your Windows 10 gold PVS image… available HERE.

Oct 192015

Sacha Thomet who was one of my competitors for the “Geekovation” contest at Synergy (he won!) wrote a PVS documentation script (http://blog.appcloud.ch/citrix-pvs-healthcheck/).  He tweeted a revision, and after looking at the code I decided to try my hand at it.  I have to give credit to Remko Weijnen (http://www.remkoweijnen.nl/blog/2012/02/29/convert-mcli-output-into-powershell-objects/) for the code to change the mcli text output into arrays, and to Martin Pugh for the code to make a pretty web report (website and info in the comments of the function).

The script requires the mcli pssnapin (https://www.citrix.com/blogs/2011/01/11/pvs-powershell-mclipssnapin/)
Here is the script http://pastebin.com/p5qBAseZ 
Edit line 131 to set the path to the html output file.
Add “invoke-expression $htm” at the end if you want it to auto launch the html report.

Feel free to edit the script – the html output is kinda dirty but it works.

pvs report

Oct 312014

I have seen where PVS targets (mainly Desktop OS) will fail to activate via KMS after booting, and/or not get the proper group policy settings.  I think this is because PVS hasn’t released the network when Windows is trying to activate/update gpo (or something along those lines).  On top of this in my environment I have PvD and Random desktops booting off of the same vdisk image.  To fix this I created the script below, and setup a scheduled task to run at startup (using SYSTEM account).

Note: Using this script you can do a lot more than just slmgr /ato and gpupdate /force commands.  For instance if you have an antivirus service that you just want to start if the vdisk is in standard mode… you could just add a “start-service” command (of course you’d want that service to be set to manual).  Feel free to edit however it suits your environment.

Steps to implement:

  1. Start a maintenance version of your vdisk
  2. Logon to that desktop/server
  3. Open powershell_ise, or notepad
    1. Copy the script below and paste it
    2. Edit line 2 to be the FQDN of your domain
      Example: yourdomain.com
    3. Save it (remember where you saved it) – I just save mine to the root of C:\ to keep it simple
  4. Open Task Scheduler
    1. Right click on “Task Scheduler Library” and select “Create a Basic Task”
    2. Name your task and optionally add a description and click Next
    3. On the Task Trigger screen select “When the computer starts” and click Next
    4. On the Action screen click Next (Start a program should be selected by default)
    5. On the Start a Program Screen
      1. Type the path, or browse to powershell.exe (C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe)
      2. in the Add arguments section:
        1. -executionpolicy unrestricted -file <path to the .ps1 file you just saved>
          Example: -executionpolicy unrestricted -file c:\startup.ps1
    6. Click Next
    7. Check “Open the Properties dialog for this task when I click Finish” and click Finish
    8. On the properties page click Change User or Group
      1. In the Select User or Group box type in “system” (no quotes) in the box and hit OK
      2. You should now see “NT AUTHORITY\SYSTEM” as the user account to run as
    9. Check the Run with highest privileges box, and click OK
  5. Perform any cleanup operations you typically do, run PvD inventory (if you use PvD), and shutdown the machine
  6. Place your vdisk into Test mode, and test away
  7. When satisfied set the vdisk to production

function startup {
while ((Test-Connection "fqdn of your domain ie: contoso.com" -count 1) -eq $null) {
Start-Sleep -Milliseconds 500
& cscript.exe c:\windows\system32\slmgr.vbs /ato
& gpupdate.exe /force
$p = gc c:\personality.ini
$r = (Get-ItemProperty registry::'HKLM\SOFTWARE\Citrix\personal vDisk\config').vhdmountpoint
if (($r -eq $null) -and (($p -like "*diskmode=p*") -or ($p -like "*writecachetype=0*"))) {

Explanation of the script:

When executed it will get the content of c:\personality.ini and the value of REG_SZ vhdmountpoint.  If personality.ini contains diskmode=p or writecachetype=0 and vhdmountpoint value is blank/non-existent it will stop the script (this indicates the vdisk is in private or maintenance mode).

PvD – value of vhdmountpoint will not be blank, so even if for whatever reason the .ini file shows the disk in private/maintenance it will go on and run the function
Shared Random – value of vhdmountpoint will be blank, but the .ini should show diskmode=s and writecachetype=something other than 0 (depends on the mode), so it will also run the function.

If the break condition is not met (indicating the disk is in shared mode) then it will run the startup function.  This function tries to ping the fqdn of your domain 1 time.  If it gets a reply it will run the activation command, and gpupdate.  If it does not, it will wait half a second and try again… over and over until it gets a reply from the fqdn of your domain.