PVS 7.6 Cache Disks on 2012R2

So…  Stood up some 2012R2 XA7.6 servers the other day, using PVS7.6 and cache in RAM with overflow to disk.

Then I saw that I had files in the WriteCache directory on the PVS server.  WTF?

After some screwing around, I found the solution.

Apparently PVS can’t use a disk that is GPT, you must use MBR.  Once I switched that and reformatted the disks, viola!  Everything worked exactly as it should.

Happy provisioning,


PVS 7.6 issues with v10 VMs on vSphere 5.5

You know, there are only so many delays I’m willing to deal with in a day.

First, there’s the bug earlier that bit me during install.  Can’t have a space in the name of the OU.

Now, I find another one that gave me the redass.  HARD.

So you’ve got vSphere 5.5.  Excellent.  Citrix says it’s supported.  Everything looks fine.  The customer wants v10 VMs, which is a pain (mostly because VMware’s web interface is a kludgy, bug-ridden POS), but whatever.  NOTE:  Yes, I’m a VCP, too, so don’t think I’m just “hatin on the competition”.  It does need work!

So you build your base image, optimize it, and install the PVS Target device driver.

Reboot, and it hangs loading windows.  I actually removed the bootux disabled entry using bcdedit just so I could see what was going on.

What’s the problem?

With v10 VMs, VMware attaches the virtual CDROM using SATA, not IDE.  Apparently the PVS target device driver can’t deal with that, so the VM never finishes loading.  NOTE:  It ONLY does this when there’s a vDisk attached – if you remove the vDisk from the target device, Windows will boot every time, so it’s not like the driver just outright breaks something.  Even more infuriating.

The solution?  Switch the CDROM to IDE.  Then, don’t forget to remove the SATA adapter from the VM.  Then after you’ve done that, make sure you go into device mangler and remove all the dead stuff – the SATA adapter itself, as well as any ATA channels that are no longer present.  You should still see two ATA channels present after the removal.  Basically, you want to remove all the grayed out items.  How?

Open an administrative command prompt, and enter “set devmgr_show_nonpresent_devices=1”.

Then, “start devmgmt.msc”

Then click view, and then show hidden devices.  Then expand IDE/ATA adapters, and remove all that stuff.


Again, remove only the grayed out items.

While you’re in there, check the Network Adapters, and remove all the grayed out NICs, too (but you already did that, right)?  *IF* you found any grayed out NICs and removed them, you should uninstall and reinstall the target device driver to ensure it binds to the correct NIC.

Then go ahead and re-run the imaging wizard, and you should FINALLY be able to pull an image of your VM.

Me?  I’m pretty disappointed in Citrix.  vSphere 5.5 has been out for a while now, and PVS 7.6 was only just released a couple months ago.  One would think they could have accounted for this, or at least made prominent note of it somewhere telling people about the problem.

But alas, here I am having to blog and complain about it.  Maybe next time..


PVS 7.6 bug

So, I’m doing my first production build of PVS 7.6 servers for a customer.  This particular customer had an OU already defined for all of their security groups. Ok, no problem, I’ll put the security groups in there for farm administrators and such.

Yeah, no.

The OU had a space in it.  The installation took just fine, but then it would not let me into the farm.  I got the old “This domain/user does not have access to the farm”.  Gee, thanks.  So, I go check the dbo.AuthGroup table.  It had a single entry, and it was correct:  “Domain.com/security groups/group”.

I moved the group to an OU without a space in the name, deleted the database, and re-ran the config wizard to create a new farm, and whuddya know?  It all started working again.

Even though Citrix wasted an hour of my time with this, hopefully you won’t waste yours.



Apparently PVS has some issues with DST.  Time doesn’t get updated correctly on targets, duh.  How does this manifest?  Event logs out of order, GPOs not getting applied, etc etc.


How do we address this?  Well, in PVS-land, one of the most important GPOs you have is the one that says “Do not change machine account password”.  If that one doesn’t work, no one can log into any of the targets because domain trust is messed up, right?  Well…   Imagine if for some reason your GPOs failed to apply!  What then??


Full info here:  http://support.citrix.com/article/ctx123336


  • Change the image mode to private image and check that the Local Security Policy Domain member: Disable machine account password changes is enabled within the vDisk image. — this is important so that the machine account password policy remains in effect even if GPOs aren’t correctly applied.
  • Resynchronize the computer before you restart.

Then to fix the time problem:

  • Click Start Run. Enter cmd to open the command window.
  • Run the following commands:
w32tm /config /update
w32tm /resync
Then restart, log in, and I recommend a gpupdate /force.  Then, shut down, flip back to standard, deal with KMS as necessary (see previous post), and you should be good.

Provisioning Server 6.1 Hotfix 18

Hotfix 18 was released yesterday.

Among other things, it addresses an issue with HA failover that can prevent devices from switching servers during an outage.


For a full list, read the article and download from here.



Trend OfficeScan AV in Provisioned VMs?

So, some mandate from above has come down and you absolutely MUST have AV in your provisioned VMs (whether they be XenApp or XenDesktop).  Forget that Citrix does everything they can to steer you away from this, and the VMs are read only, and….  Well, you get the idea.  Either way, the powers that be said that there must be AV, and they are willing to pay for Atlantis or SSD storage or whatever it takes to make sure you’ve got enough IOPS to feed it.

So you say to yourself “Ok, it’s not my money anyway.  As long as the performance is there and the end users get a solution that is acceptable to them, it makes no difference to me.”  And then, the hard part:  How do you make it work??  Trend registers each client machine against the OSCE server using the GUID of the installed Trend OSCE client, NOT the machine’s SID.  But, since all the machines are basically carbon copies of that one base image, what’s a guy to do?  So, you went home, you pulled out your hair, you drank some beers to get over the headache this all caused you, and now, you’ve wound up here.  Fear not, brave Citrix admin:  I’ll show you the way.

Now, anyone with some decent Googlefoo can certainly run across another blog from some guy with a surname I can’t pronounce and with a TLD of .eu.  That’s where some of this came from.  However, I found the information there to be less than completely helpful, and, moreover, it didn’t solve the issue completely (not to mention the code needed help – option explicit, unused declared variables, scoping issues, etc).  What to do?  Improve, of course.

Step 1.  Copy this code into a vbs script of your choosing (this is for x64 VMs – if you want it for x86 VMs just edit the registry read/write lines to take out wow6432node)

On Error Resume Next
Set oShell = WScript.CreateObject("WScript.Shell")
Set oFS = CreateObject("Scripting.FileSystemObject")
sCacheDrive = "d:\"
sFolder = sCacheDrive & "\Trend"
sFile = "Trend.txt"
sLogPath = sFolder & "\Trend_log.txt"
If oFS.FileExists(sLogPath) Then oFS.DeleteFile(sLogPath)
If oFS.DriveExists(sCacheDrive) Then
If oFS.FolderExists(sFolder) Then
If oFS.FileExists(sFolder & "\" & sFile) Then
LogFile (sFile & " file found. Exiting script.")
Set oFile = oFS.CreateTextFile(sFolder & "\" & sFile)
LogFile (sFile & " file not found. Running Check_Trend procedure.")
LogFile ("Check_Trend procedure complete - exiting script.")
End if
LogFile (sFolder & " not found. Creating folder and file.")
oFS.CreateTextFile(sFolder & "\" & sFile)
LogFile ("Running Check_Trend Procedure after creating folder and file.")
End If
LogFile(sCacheDrive &" drive could not be found. Quitting the script.")
End if

Sub Check_trend
sFile2 = "ImgSetup.exe"
sSource = "C:\Trend\Trend\"
sDestination = "C:\Trend\"
LogFile ("Adding Run command for imgsetup.exe.")
oShell.RegWrite "HKLM\SOFTWARE\Wow6432node\Microsoft\Windows\CurrentVersion\Run\Trend OfficeScan ImageSetup", chr(34) & sDestination & sFile2 & chr(34) & " -HideWindow", "REG_SZ"
If Not oFS.FileExists(sDestination & sFile2) Then
LogFile (sDestination & sFile2 & " not found.")
LogFile ("Copying " & sFile2 & " from " & sSource)
oFS.CopyFile sSource & sFile2, sDestination
End If
LogFile ("Running Trend Sysprep.")
oShell.Run chr(34) & sDestination & sFile2 & chr(34), 0 , True
sRegGUID = oShell.RegRead ("HKLM\SOFTWARE\Wow6432node\TrendMicro\PC-cillinNTCorp\CurrentVersion\GUID")
LogFile ("GUID =" & sRegGUID)
LogFile("Writing " & sRegGUID & " to the " & sFolder & "\Trend.txt file.")
Set oFile = oFS.OpenTextFile(sFolder & "\" & sFile, 2)
oFile.WriteLine sRegGUID
LogFile ("Starting the Trend Realtime scan service.")
oShell.Run "net start ntrtscan", 0, TRUE
LogFile ("Script Finished.")
End Sub

Sub Read_GUID
Set oFile = oFS.OpenTextFile(sFolder & "\" & sFile, 1)
LogFile ("Running Read_GUID procedure.")
Do While oFile.AtEndOfStream = False
sLine = oFile.Readline
LogFile ("Writing GUID " & sLine & " to the registry.")
oShell.RegWrite "HKLM\SOFTWARE\Wow6432node\TrendMicro\PC-cillinNTCorp\CurrentVersion\GUID", sLine, "REG_SZ"
LogFile ("Starting tmlisten.")
LogFile ("Starting ntrtscan.")
oShell.Run "net start tmlisten", 0, TRUE
oShell.Run "net start ntrtscan", 0, TRUE
LogFile ("Script Finished.")
End Sub

Sub LogFile(Message)
Set lFile = oFS.OpenTextFile(sLogPath, 8, True)
lFile.WriteLine Now & " - " & Message
End Sub

Modify line 4 in the VBS above to reflect your cache drive letter.  Sorry the formatting got wrecked, blame it on the WP editor.  PLEASE TEST this before just stuffing it into production!  I am not responsible for your copy/paste/fail maneuvers if you don’t at least have a basic handle on VBS and can’t identify a code fragment that belongs on the previous line (nor am I responsible for any other reason, use at your own peril, etc etc — but I digress)…

Step 2.  Copy this code into a cmd file and name it whatever you choose.

REG Delete "HKLM\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Run\Trend OfficeScan ImageSetup" /f
REG Delete "HKLM\SOFTWARE\Wow6432Node\TrendMicro\PC-cillinNTCorp\CurrentVersion\GUID" /f
del c:\Trend\imgsetup.exe
del c:\Trend\TmEngDrv.dll
del c:\Trend\TmPfwApi.dll
del c:\Trend\TmProxy.dll

Step 3.  Go into your VM in private mode.  Create the folder C:\Trend, and then create the folder C:\Trend\Trend.  Then, from your OCSE server, copy the file imgsetup.exe into the C:\Trend\Trend folder.

Step 4.  Install the Trend OfficeScan client (This solution tested with 10.5, BTW).  After it’s installed, unload it.  Then set all three of the OSCE services to MANUAL startup.

The VBS script above?  Add it to either the local policy of the image or to a GPO as a startup script.  The CMD above?  Yup, you guessed it, shutdown script.

Then, seal up your VM and shut it down.  Viola!  No more phantom registrations and offline VMs and all sorts of other weirdness in your OCSE reporting console.  Also, I would highly recommend that you create an auto-add domain (by IP, because your provisioned VMs are in a dedicated network, RIGHT?), and apply the correct AV exceptions to that domain.  Don’t know how to do that?  Google got you here, it’ll get you there.  😉


SQL mirroring for Citrix

So, you’re building a XenDesktop environment and you want to mirror the database for it.  while you’re at it, why not mirror PVS and XenApp, too?  They both support it.  But how do you do it?  You’re a Citrix admin, not a database admin!

Start by installing SQL Standard (or Enterprise) on two different servers.  Do NOT put the databases on the system drive!  Otherwise, just a vanilla install is fine (make sure to install SQL management studio).

For XD – create an empty database on the first SQL Server and call it whatever you want (XenDesktop is nice, but whatever).  The collation needs to be LATIN1_GENERAL_CI_AS_KS , and the recovery model needs to be set to full.  Also, make sure you have configured the proper permissions for your XenDesktop service account to access the database.  Then – create a new query and enter the following:

BACKUP DATABASE [XenDesktop] TO  DISK = N'C:\temp\XenDesktop.bak' WITH NOFORMAT, NOINIT,  NAME = N'XenDesktop-Full Backup', SKIP, NOREWIND, NOUNLOAD,  STATS = 10

Then right click in the query window and select execute.  Copy the file XenDesktop.bak to the second SQL server.  Right click Databases and select Restore Database.  Enter XenDesktop as the database name, then select From Device, and browse to the file.  Then, check the box in the display next to the file name.  Then click Options in the left pane, and then make sure to select “without recovery”.

Now, go back to the first SQL Server and right click the database and then in the left pane, click Mirroring.  Click Configure Security.  Make sure the box for Witness Server is unchecked (if you want a witness, you can read more about it on MSDN, but this is a Citrix blog, not a SQL blog, so we’re keeping it simple).  Then enter the information for both the SQL servers.  Then for the account, use your SQL service account for each server (your SQL Servers do use a service account, right?  If not, go change it now – because if you want to use local system or network service, you need to use certificates, and I HATE certificates!).  Since the SQL servers in my deployments are generally dedicated to Citrix databases, I like to use the same service account for both servers.  If you use a different one for each server, just make sure you enter the correct one for each server.  After the wizard completes, click start mirroring.  That’s it.

Repeat the process for XenApp and PVS, changing the database names and .bak file names appropriately.  PVS and XenApp don’t much care about the database collation type like XenDesktop does.  For XenApp, though, you need to download the Native SQL client for the version of SQL Server you are using (2008 R2 is still the easiest with all the additional restrictions imposed by 2012).  After it’s downloaded, stop the IMA service, install the new client, and then open MF20.dsn and modify it thusly:

The Driver line should read

DRIVER={SQL Server Native Client 10.0}

Then, under the line beginning SERVER=, add the following line:


Obviously, put the name of your SQL Server in there.

Then just start the IMA service back up.

Nothing special should need to be done with PVS, provided the databases are correct.