Citrix, Office 365, PowerShell

Redirecting Folders to Office 365

I created a script a while ago to map folders at logon to enable saving directly to OneDrive for Business (also known as SharePoint Online or SkyDrive Pro). I plan to explain more on this but it was the script I mentioned in my #SYN119 presentation at Citrix Synergy 2014.

This script is now up and published on codeplex and is under the GPLv3 license (a copyleft license). Feel free to use and modify if you can help. Below is a slight description of what the script does and why it was created.

This project is to enable the use of Office 365 as redirected folders in Microsoft. Specifically, this script and method can be used on a Windows 7 desktop (or higher) with Citrix and roaming profiles (or any persistent profile method). What makes this unique is that no local storage is used (unless you can’t connect to office 365 and then it’s only temporary).

This script was developed by Tyler Bithell and Tom Gamull for a customer implementation. The customer desired a method to eliminate the use of local or shared storage and leverage their Microsoft Office 365 subscription.

You must have a subscription that gives you the SharePoint Online (Groove, SkyDrive Pro or OneDrive for Business). This is NOT the same as SkyDrive or OneDrive (these are just an online storage method, like Dropbox).

We leverage a method of WebDAV drive mapping utilizing NET USE. Although you can utilize OneDrive for Business for Microsoft Office applications directly, non-integrated applications are not able to be used except through navigation to the folder. This is often a problem for task works, students and others used to using My Documents or Downloads. Therefore this script was created to deal with this issue.

The script was announced but not shown at the Citrix Synergy 2014 conference in #SYN119. This script will also be discussed in the Cisco Live session Tom Gamull is presenting on Atlanta Public Schools.

Citrix, SQL, XenDesktop

XenDesktop 7.1 SQL Mirroring

Mirroring in SQL is a great way to protect your XenDesktop infrastructure. In 7.1 deployments this can be a bit challenging since the documentation at Citrix doesn’t reflect an accurate way to accomplish this goal.

First let’s go over some basics. SQL Mirroring is a 3 server setup with a primary SQL server running a database, another secondary SQL server also running the database and a third SQL witness server which does NOT run the database (runs SQL, just no data). If you use local disk, this is an excellent setup. If you have two storage appliances, this is a great setup. If you have one big SAN, this doesn’t make much sense. To make mirroring worthwhile, you need 3 SEPERATE storage locations for each server. If you have two servers on the same storage, mirroring will not provide much value (other than a learning opportunity). I feel this is where people can easily forget why you mirror.

To demonstrate why, let’s say I have a two node management cluster, one host runs my primary SQL server and the other runs my secondary and the witness. I put the primary on the local disk of HOST1 and the secondary and witness (which is lightweight) on the local disk of HOST2. I have an issue. Let’s say HOST1 goes down, HOST2 is up and SQL stays up just fine because we have one of the mirrored servers running PLUS the witness. Let’s say I accidentally shut down the witness. No problem. Let’s say I shutdown HOST2 or do maintenance. Now I’ve got a problem. When the primary SQL server can’t see the witness AND the secondary SQL server, it stops. This is by design, it doesn’t know if it’s orphaned. It assume those two other servers don’t see it but must be serving the data. If I simply use a witness on a third unique HOST and storage area, my mirror is looking great! If I only have 2 hosts or shared storage, this is where a cluster makes sense. Clusters cannot survive storage failures, but mirrors can. However, you are writing to both storage locations at the same time. Often I’ll use two unique SANs and put the witness on local disk. I can now survive a storage appliance failure, however it’s only as good as having three different points of failure instead of one.

SQL Mirror

With that said, my main topic was how to get this done on your XenDesktop 7.1 controllers. This appears to have been posted other places but since I had to do it I thought I’d share also. There is an excellent post at Citrix on this here. here.

I did this manually below but I heavily recommend downloading his script and giving a shot before manually doing this.

I want to add one caveat, you MUST create the machine account logins in SQL on the mirror. So you’ll need to do this after a forced failover to the mirror. In addition, you may also need to delete the machine accounts and add them back if you migrate the SQL database, say from SQL Express to Standard/Enterprise for example. This is what worked for me, hopefully it helps

Now for this next part, I like to do this one controller at a time. If you mess up you can’t really go back and fix things if your controllers get orphaned. This is why during upgrades, you only partially update the farm, in case you need to roll back.

$cs = "Server=YOUR_SQL_SERVER_NAME;Initial Catalog=YOU_SQL_DATABASE_NAME;Integrated Security=True"

Set-LogSite -State Disabled
Set-LogDBConnection -DataStore Logging -DBConnection $null
Set-MonitorDBConnection -DataStore Monitor -DBConnection $null

Set-MonitorDBConnection -DBConnection $null
Set-AcctDBConnection -DBConnection $null
Set-ProvDBConnection -DBConnection $null
Set-BrokerDBConnection -DBConnection $null
Set-EnvTestDBConnection -DBConnection $null
Set-SfDBConnection -DBConnection $null
Set-HypDBConnection -DBConnection $null
Set-ConfigDBConnection -DBConnection $null -force
Set-LogDBConnection -DBConnection $null -force
Set-AdminDBConnection -DBConnection $null -force

Another way to clear the controllers out

$controllers = Get-BrokerController | %{$_.DNSName}

foreach ($controller in $controllers)
Write-Host "Disconnect controller $controller ..."

Set-ConfigDBConnection -DBConnection $null -AdminAddress $Controller
Set-AcctDBConnection -DBConnection $null -AdminAddress $Controller
Set-HypDBConnection -DBConnection $null -AdminAddress $Controller
Set-ProvDBConnection -DBConnection $null -AdminAddress $Controller
Set-BrokerDBConnection -DBConnection $null -AdminAddress $Controller
Set-EnvTestDBConnection -DBConnection $null -AdminAddress $Controller
Set-SfDBConnection -DBConnection $null -AdminAddress $Controller
Set-MonitorDBConnection -Datastore Monitor -DBConnection $null -AdminAddress $Controller
reset-MonitorDataStore -DataStore Monitor
Set-MonitorDBConnection -DBConnection $null -AdminAddress $Controller
Set-LogDBConnection -DataStore Logging -DBConnection $null -AdminAddress $Controller
reset-LogDataStore -DataStore Logging
Set-LogDBConnection -DBConnection $null -AdminAddress $Controller
Set-AdminDBConnection -DBConnection $null -AdminAddress $Controller

If the last two won’t work, try adding -force on the end. If they still don’t do the following (may need to reboot)
Get-Service Citrix* | Stop-Service -Force
Get-Service Citrix* | Start-Service

Ok now it’s time to go mirror, once you’re done setting up the mirror set the database on ONE of the servers only and verify it before moving to the next one(s)

You already set the $cs variable but if you opened a new window or lost it, set it again

$cs = "Server=YOUR_SQL_SERVER_NAME;Initial Catalog=YOU_SQL_DATABASE_NAME;Integrated Security=True"
set-ConfigDBconnection -dbconnection $cs
set-AdminDBconnection -dbconnection $cs
set-LogDBconnection -dbconnection $cs
set-AcctDBconnection -dbconnection $cs
set-BrokerDBconnection -dbconnection $cs
set-EnvTestDBconnection -dbconnection $cs
set-HypDBconnection -dbconnection $cs
set-MonitorDBconnection -dbconnection $cs
set-ProvDBconnection -dbconnection $cs
set-SfDBconnection -dbconnection $cs
Set-LogDbConnection -DataStore logging -DbConnection $cs
Set-MonitorDbConnection -DataStore monitor -DbConnection $cs

Set-LogSite -State Enabled

$testString = Get-BrokerDBConnection
Test-BrokerDBConnection $testString | fl

Now make sure you TEST FAILOVER before declaring success.


XenDesktop 7.1 and Storefront long log on times

First of all this is really just a cut-and-paste from a talented co-worker, Jason Allen.

All I ran into an issue with XenDesktop 7.1 and Storefront 2.1. I was having long log on times when connecting via storefront internally (30 seconds) and it was all on the HDX connection. If I logged on via the Netscaler the logon was 10 seconds. After going through Citrix escalation we saw that the receiver/XD7 was trying to connect via 2598 and would time out and default to 1494. I had specifically disabled session reliability via policy which disables the 2598 port listener. Apparently this causes an issue with XenDesktop 7.1. I removed the session reliability policy (left it default at not configured). Rebooted the servers so 2598 listener was listening and problem was gone. So keep this in the back of your head and do not explicitly deny session reliability in XD7.1. Hope this saves you guys from some headaches!

Further research by Jason also found that the issue only appears if session reliability is disabled AND the firewall is on.  Quoting him below.

“Guys – I just tested this in my lab today, the issue only appears when session reliability is disabled AND the windows firewall is on. Even though 2598 is allowed through the windows firewall it was still causing a problem. I tested with session reliability disabled and windows firewall disabled and the connection speed was normal. I emailed this information to the Citrix Escalation engineer but thought I would share my findings.”

Hope this helps anyone.  Personally I usually leave Session Reliability on in my deployments but most people who have done this a while always leave it off.  XenDesktop 7 and 7.1 have greatly improved the feature but also the need for it is the proper determining factor. Anyone, hope this helps a few people out there and if you are a customer in Boston, know Presidio has some great engineers up that way and we’re looking out for you.

Citrix, DNS, PVS, XenApp

XenApp, PVS, Hyper-V and NIC issues – 1494 not listening

While spinning up about 100 xenapp servers on hyper-v, I utilized a PVS isolated stream network.  This network, on Hyper-V, needs to use the legacy NIC.  It is a different subnet than the backoffice network, which utilizes the 10GE NIC.

For some reason, several of my XenApp servers seem just fine except they won’t connect (RDP works fine).  I let Citrix support take a shot at this but here is what I found.

netstat -a shows the 1494 port listening on the wrong NIC.  This often occurs if the NIC needs to be recreated (I have no idea why some VMs have a #2 or #3 NIC, I plan to take care of that later).

I tried to use many CTX articles to figure this out, but nothing I tried seemed to work (this included editing the httpd.conf, setting DNS lookups, NIC binding, ICA listener configs).  Nothing would seem to change the IP of the 1494 listener.

Getting a bit frustrated, I stepped back and figured something must be locking that port.

netstat -a -b

Shows me TermService is using 1494.  I restart TermService and all troubles just disappeared.

Thinking this through, what happens is if the VM needs to create the 10GE NIC (for whatever reason) it doesn’t wait to start TermService, which means TermService locks 1494 and doesn’t let IMA/XTE use it, no matter what you say in the ICA configuration settings.  In fact, ICA Configuration isn’t correct when it reports what Network Interface it listens on, it seems it doesn’t know (even all NICs isn’t correct).

In any case, I paused and stepped back.  Looking further into the issue, XenApp could not get the right IP for some of the VMs and this led me to look at DNS.  The customer had a master domain (where the infrastructure servers resided) and a child domain, where the XenApp servers resided.  Due to stale records on the DNS of the primary domain (3rd party DNS/DHCP provider) I had to force DNS lookups on the infrastructure servers to use the child domain first (eliminating a bad DNS entry in the root domain).  Magically everything worked.

I actually noticed this post in draft mode today and just added the part at the end realizing the issue had been resolved.  If the DNS/domain setup is strange, ensure lookups are working before going too much further.

Citrix, PVS

Citrix PVS – Hiding the Boot Menu

I hadn’t really thought much about it but on a deployment realized there must be a better way!  For those of you who work with PVS and update/test the versioning feature in PVS 6.+, you know that you must be on the console and press 1 + Enter at some boot menu to get maintenance target devices to boot from the maintenance image.  I have no idea why you would assign a maintenance image to a maintenance target device and not want it to boot from that but I’m sure there is a reason.  In any case, it always seemed odd you need to console in to do that.

I decided to look for a better way and this may be old news to some of you.

Brian Cahill in the Citrix Forums informs of a way to set a registry key to skip the menu.  Restart the stream service once you make the change and you should be good to go!

You can set the following registry key on all the PVS servers.
HKLM\Software\Citrix\ProvisioningServices\SkipBootMenu DWORD

Value Behavior
0 or not defined Normal behavior <default>
1 Don’t send a boot menu to device. Automatically pick the first item that would been on menu and act as if it was the only version assigned.

Citrix, CloudGateway Enterprise

CloudGateway Enterprise (coming soon)

I’ve been working on perfecting a CloudGateway Enterprise in the lab guide.  I don’t believe there is a good one out there demonstrating full load balancing and remote SQL and all that (which if you’re going Enterprise I think you need to know!)

Most recently I had an issue with SQL auth.  I had to enable DebugView and Verbose logging on the Storefront server to find this.  In any case, I ended up creating a new database and pointing Storefront towards it.  I expected to have to reinput everything but I didn’t, it worked just fine.