OK. I did an article recently on how to deploy file type associations (from hereon in, referred to as FTAs) on Windows 8.x/Server 2012 R2. However, the method I finally settled on in that article turned out to be a little hit-and-miss, particularly when using security groups from AD, as borne out by the comments and emails that I received regarding it. Fortunately, myself and Mr Duncan Murdoch (who deserves a whole load of credit for doing a very comprehensive deep-dive on the inner mysteries of FTAs) put our heads together and had another stab at this, mainly looking at it from a perspective of XenApp systems (specifically, Server 2012 R2 running XenApp 7.6 Feature Pack 3).
Note - the original article has now been removed, as it was very inconsistent. Please use this one as the reference for this subject from now on!
It would probably help to do a bit of a recap of the issues and drivers behind this from the previous article, so if you've read the first one and feel like there's a bit of crossover, my apologies! However, now that the original post has been removed from the blog,it makes sense to reproduce the original background here in full.
We're all familiar with FTAs - they are the program that opens a particular file type. Files with the .docx extension open in Microsoft Word. Files with the .txt extension can open in many things - Notepad, Notepad++, even Microsoft Excel. Each user normally has a default FTA that is the program that will open it when you double-click a particular file type. If you wanted to open the file type in a different program (for instance, open a file with the .xml extension in Notepad instead of the default of IE), you can right-click on the file and choose Open With.
So why would you want to assign FTAs on a per-user basis?
Mainly, we're talking about shared systems, and for the purposes of this article we're specifically concentrating on Citrix XenApp (although this should work just as well for Server 2012 R2 Remote Desktop Session Host). When you're in a shared-session environment such as XenApp, you might want users to open files from the same server but with different applications, possibly for licensing reasons, or possibly just for user convenience and familiarity. You might want some users to open Visio files in Visio, and others in Visio Viewer. Or you might want some to open PDFs in Adobe Reader but others in the full version of Acrobat. In Windows 7/Server 2008 R2/XenApp 6.x, you could simply use Group Policy Preferences Folder Options to deploy an Open With item. Each user would get a particular application associated with a particular file extension when they logged in. Nice, easy, uncomplicated.
Enter Windows 8.x and Server 2012 R2, which is where our nice shiny new XenApp 7.6 systems sit, and Microsoft have moved the goalposts (quelle surprise). The Group Policy Preferences method I wrote about previously simply flat-out doesn't work any more. Normally, user FTA settings are written to a specific Registry area - HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts, with subkeys for each filetype (e.g. .PDF). But Microsoft appear to have changed something. Now, when you write a new filetype using the Default Programs part of Control Panel (or the Open With context menu), the Registry settings are changed in a very different way.
To show you what I mean, I've logged on to a Server 2012 XenApp 7.6 FP3 system with three different PDF readers installed locally (Adobe Reader, Foxit Reader and SumatraPDF), and I'm going to select FoxIT Reader as the applicaton to use. The way I trigger this is by right-clicking a PDF file and choosing Open With | Choose Default Program, but you can also access this through the Control Panel.
Once I select FoxIT Reader as the default program, we can see the Registry changes we'd expect - but there are some additions we haven't seen previously
Note the Hash value. Apparently, this is a hash generated from the application, the computer name and the username, and which needs to be unique in order for this key to be used. So if I export these values into the user profile and roam them to another XenApp server, the FTA will be lost. If you export, roam, save or persist this Registry key, when you move to another server system, you are prompted to choose the default program again, because the hash doesn't match. Apparently this was done to reduce tampering by malware, but it's very short-sighted because it doesn't take into account multi-session systems like XenApp and RDS.
Even more annoying, is the fact that the action of setting a default program in this way also writes a permissions change to the UserChoice key. See below
Note the Deny set for the user account that made the change (in this case I was logged on as Administrator). This means that you can't set the values in this key through a script or such like without altering the Registry permissions first. But even if you do alter the permissions, you need the Hash value to match the server system - and without knowledge of the algorithm in use, you're not going to get very far.
However, Microsoft have handily made a function available for setting the file associations. This involves setting the file association(s) for a user, and then exporting it(them) out to an XML file using the following command
Once you've exported the XML file with your configured file associations (you can edit it by hand to just get the FTAs you need), you can then deploy this at logon by using a Group Policy Object. This all sounds good so far...
...until you realize that the GPO that sets the FTA is Computer Configuration only. That's right, it writes to a Registry key in HKEY_LOCAL_MACHINE. Making it a royal pain in the proverbials for deploying to multi-session environments such as XenApp. If you don't believe me, check it out - it's to be found only in Computer Config | Policies | Admin Templates | Windows Components | File Explorer
So somehow, we've got to try and use the information in an HKLM policy value to deploy per-user settings. Not a very good starting point. In fact, even though we tested this and made it work to a certain extent in the previous article on this, it would have been very difficult to make this work on XenApp. Imagine if ten users opened sessions on the server at once, and all of them were trying to rewrite and import in the relevant policy key from a single area in HKLM? It would be chaotic.
And (possibly fortunately), the method seemed to be very inconsistent anyway. Sometimes the user would have to log in twice to get the FTA correctly applied. If you're in a XenApp environment, this would be unworkable, particularly if users were hitting any one of a pool of servers (or even desktops).
So - this is where Duncan stepped in. I've often hung around conferences with Duncan chewing the fat, and he does some very interesting work with App-V and FSLogix over on his website at www.amberreef.co.uk. He did some excellent deep-dive work on the inner mysteries of FTAs, and together we managed to come up with something that looked like it might just work...
A quick recap - we have a Server 2012 R2 instance running XenApp 7.6 Feature Pack 3. We've installed three PDF readers on here - Adobe Reader, Foxit Reader and SumatraPDF. We will set up three AD security groups to assign different FTAs dependent on the user's group memberships. We will also give our test user a mandatory profile to ensure that nothing is being saved locally to the box.
However, the first thing you will need to know to use this method is the filetype. Older heads may remember the ftype command which is probably still around in the guts of Windows today. Running this command gives you a list of all registered file types on the machine - something like this
You will need to get the relevant filetypes for the applications you are switching between. The best way to tell is pick a clean machine and install the application onto it. Most applications will register themselves as the default handler once you install them for the file extension you're dealing with (so, for instance, .pdf for PDF readers, .vsd for Visio, etc.) So once you've installed the application, jump into the Registry and check HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.extension\UserChoice (where extension is the file extension you're concerned with) and look for the Progid value. As an example, I've just installed Sumatra PDF onto my local machine (replacing Adobe Reader), and I can now see this entry in the Registry key I specified
So the filetype I am looking for is Applications\SumatraPDF.exe. Incidentally, if the program isn't as pushy as usual and you can't find the filetype here, use the Open With context menu command to set it as the default program for opening the particular extension, and it will then write here as necessary.
Following this on logically by installing the other applications, I find the latest version of Adobe Reader has a filetype of AcroExch.Document.DC, and Foxit Reader has FoxitReader.Document. Bear in mind that these may change from version to version, so don't take these ones as gospel if you're dealing with these specific applications!
Now, we need to take this information and utilize it, and this is where we seem to have come up with a way to defeat the hashing and permissions and HKLM-only crap that Microsoft are trying to foist on us. What we are going to do is delete the user's default file extension handler from the Registry as the user logs in, but write the filetype into HKCU\Software\Classes\.extension. Our testing showed that if you remove the entry from the FileExts key, it checks HKCU\Software\Classes for the filetype it should use.
Tools-wise, you could do this with a script (a very rough and ready sample is given a little later), but given that I have in the past done a lot of AppSense stuff, it made sense for me to leverage the power of DesktopNow to test this foremostly. Naturally, there is a whole ecosystem of products or scripting languages you could use to achieve this on XenApp - pick your poison as necessary!
I put this in the Desktop Created trigger but this was probably not necessary - I am fairly sure it should run just as well in Pre-Desktop.
Firstly I created a Condition for each of my AD security groups
Next, inside of each Condition, I nested a couple of Actions. The first was to delete the entire key that referred to the user-defined settings
Despite the Deny permission I wrote about earlier, this entire parent key should be accessible to the user, so there's no need for elevated access.
Next, we simply set the default value in HKCU\Software\Classes to the required filetype. Be very careful here - you need to use the AppSense Action for Registry | Set default value rather than Set value. So for our first group, we set up SumatraPDF in this area
The second one gets Adobe Reader
And the third, Foxit Reader
So our whole nested set of Actions should now look something like this
If you wanted to do this with a script, you could maybe experiment with a few AD logon scripts using Security Filtering to scope the logon script to the AD groups in question. PowerShell would be the easiest way, but if you wanted a quick bit of batch, this sort of thing should suffice (lines may wrap)
reg delete HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\.pdf /f
reg add HKCU\Software\Classes\.pdf /v "" /d FoxitReader.Document /f
Note that this is for Foxit Reader - substitute the required filetype as necessary
So now we need to deploy this to our XenApp server and log on our test user. Firstly, we will make him a member of the first group (and ensure we have a PDF file on the desktop so that we can see the association straight away). Firstly, he should be assigned SumatraPDF as the reader of choice. Let's see...
...and it looks good. Now let's try with our user in the second group, so he should get Adobe Reader...
...and it looks excellent, another good result. Finally we will create a new user and assign him to the third group, where he (or she!) should get Foxit Reader...
...which is exactly what it does. Brilliant!
Just for posterity, I spun up a second XenApp 7.6 system just to ensure that all of the "testing" (which broadly correlates to us deleting stuff and seeing what we'd got around) hadn't given us some Frankenstein-esque system that was simply playing ball just for the hell of it. Apart from having to make sure the software application versions matched the filetypes (trying to use the AcroExch.Document.DC filetype with Adobe Reader XI resulted in some awkward moments - it should have been AcroExch.Document.11!), it all seemed to work very well.
The issue with "roaming" selected FTAs from machine to machine, however, is one that we will have to visit in another post, however, hopefully the pointers here might have some mileage for this problem as well in the meantime. Duncan mentioned that he was looking at a scripted way of doing this (although I'm sure he's very busy with other stuff), but it's definitely something that also needs addressing.
Anyway - hopefully this should provide a method of applying per-user FTAs for those of you who have to deal with this on XenApp or XenDesktop systems (or RDSH, for that matter). It certainly did the trick in my lab - I'd be interested in finding out if it works in the wild, because the interplay between the various areas of the Registry and the file type handlers certainly makes for a fairly complicated subject.
Big kudos due to Duncan for taking the time out to dive into this - hopefully we won't have to go down this route again! :-)
Update - I built a third XenApp server, just to be sure, and this time the solution wouldn't work until I removed the Registry key HKLM\Software\Classes\.pdf. If you have problems with this, this may be something to check in your gold image/template/however you deploy a server.
Update - I built a third XenApp server, just to be sure, and this time the solution wouldn't work until I removed the Registry key HKLM\Software\Classes\.pdf. If you have problems with this, this may be something to check in your gold image/template/however you deploy a server.