## Incorrect byte order mark when importing a Citrix license

For anyone else that gets the above error when adding a Citrix license in Studio – open the file in notepad, do a save as (double check the encoding is UTF-8, most likely it already is), add the saved as file to Citrix. That’s all. :)

I am proud of this one. Spent a lot of time working my way through this even though I don’t know much SQL and finally cracked it. Probably not a big deal for any “experts” out there but this pretty much was the highlight of my day. :)

A colleague of mine setup a new Citrix site and went for holiday, without giving the rest of us admin access to the site. As expected we needed to access it and while we were waiting for him to get in touch to our messages I thought there must be a way to hack into the system. There is a database behind the scene after all, so if I could just get access to that then maybe I can give myself admin access.

Turns out there is.

We had gone with SQL Express with both delivery controller and SQL server on the same machine, and thanks to this Citrix support article I learnt that in such a case the ‘NT AUTHORITY\NETWORK SERVICE’ account is used to login to the SQL server (that article is a good read for other scenarios too BTW). Cool. I knew I could run something as ‘NT AUTHORITY\NETWORK SERVICE’ using SysInternals PSTools. So I downloaded PSTools to that server, opened a command prompt as admin, and ran the following:

All good so far. Next I downloaded SQL Studio and ran that from the above command prompt. Just type "C:\Program Files (x86)\Microsoft SQL Server Management Studio 18\Common7\IDE\Ssms.exe" into the command prompt window. That will give you the login prompt and you can connect (if it asks for any details the server name is “<your server name>\SQLEXPRESS” and authentication is “Windows Authentication”). This worked and I was in! Yay.

Snooping around the various SQL tables I came across [DAS].[Administrators] which looked like it could contain the administrators. Did a right click > “Select Top 1000 Rows” (remember I am no SQL guru) and that opened a new query which I executed … and sure enough I could see the sole admin account of my colleague who’s on holiday. Nice! Seems to be a list of SIDs followed by a UserIdentityType column of value 0 and Enabled column of value 1. Hmm, maybe I can just add to this table and be done with it? Did a bit of Googling on how to insert into a table, found my SID from psgetsid of the PSTools I had already downloaded, and tried the following:

And … that didn’t work! Got the following error: “The INSERT permission was denied on the object ‘Administrators’, database …”

Oh well, worth a shot. I looked around the user accounts on the SQL server and the roles and permissions for the network service account and from what I could see it has all the rights it needs. There’s no other account. So surely that’s what the Delivery Controller too is using to add new admins etc. Time to read more.

Back to the Citrix support article I came across earlier, I found the same roles that I had found on the SQL server and also this bit: “Each one of the preceding roles has the minimum permissions granted to it to allow the corresponding service on the controller to function. These permissions are restricted to execute on stored procedures and read on some tables.” Ah ha! So it has permissions to only execute stored procedures and that’s obviously how it is adding admins. Cool!

Obviously I have no idea what a stored procedure is, so time to Google again on how to get to that. Did that, and found a ton of them them under Programmability > Stored Procedures. The table was called “DAS” something so upon a hunch I looked around any procedures starting with “DAS” (not entirely a hunch, I noticed that the procedures seemed to start with similar names as the tables so I made a guess that probably the stored procedures for the “DAS” tables would start with the same name). That paid off and I found “DAS.NewAdministrator”. Cool!

Note to anyone else: to see a stored procedure you right click and do “Modify”. That shows you the code. You can run it via right click > “Execute Stored Procedure” which will give a popup to enter the parameters for the procedure. This part stumped me for a while. I entered the parameters as best as I could figure but it kept throwing various errors. That’s when I spent some time looking at the procedure code and cracked the problem. Once you enter the parameters SQL Studio generates a query which you execute, and that was giving errors. I figured the issue and modified the query. It looks like the below in case anyone else wants to copy-paste and modify:

And that worked! Whoo hoo. Still can’t access via Studio, but I double checked the [DAS].[Administrators] table and my account was there.

Hmm, maybe the issue is that I have added myself as an admin but I haven’t granted myself any rights. Remember when you do this via the Studio you have to select a scope and also what rights you want to assign? Probably got to do that via SQL! Not a problem, back to Google. :)

I came across another Citrix article (why didn’t I just find this the first time!? it tackles pretty much what I am doing here. anyways, the first few steps of that article are incorrect as that’s what I too had tried and it didn’t work for me … so good I didn’t stumble upon this initially). This one showed me how to give my admin account rights and scope. Here’s the additional SQL you need to run:

No rocket science here. It uses another stored procedure called “DAS.AddRight” to give my SID “Full Administrator” rights to the scope of “All Objects”. That completed without any errors, so I closed and opened Citrix Studio and yay I am now in!

And that, ladies and gentlemen is how you get into Citrix Studio if you don’t already have access! :)

## Receiver Self-Service: Cannot Contact Store

Was trying to setup receiver self-service in one of our newer sites and it kept error. (This affects receiver for iOS and Android too by the way, which is how I first came to know of this problem). Had a lot of little configuration errors that needed fixing, but the last one (which is the title of this post) had me stumped for a while.

• Ensure that there’s a separate session policy for receiver self-service. More importantly:
• Ensure that the expression for the policy includes the case for iOS devices too if you are interested in that (i.e. REQ.HTTP.HEADER User-Agent CONTAINS CitrixReceiver || REQ.HTTP.HEADER User-Agent CONTAINS 'CitrixReceiver-iPad' || REQ.HTTP.HEADER User-Agent CONTAINS CFNetwork || REQ.HTTP.HEADER User-Agent CONTAINS Darwin)
• Not critical, but as a good practice – ensure that your receiver for web policy and receiver self-service policies have equal priority so there’s one less thing to look at when considering these policies.
• Ensure that the single-sign on domain in the receiver self-service matches the trusted domains you define in the Citrix Storefront.
• Remember that web authentication uses LDAP as primary & RADIUS as secondary; while self-service authentication uses RADIUS as primary & LDAP as secondary, so double check these are setup accordingly with the correct expression to match web or self-service.
• Ensure that the receiver self-service policy has the SECONDARY credentials ticked for single-sign on.

If the authentication stuff is incorrect you will keep getting prompts that the login is incorrect. Also, the StoreFront logs might contain errors that the user domain isn’t a trusted one etc.

In my case even after doing all this I was getting an error. I was able to successfully login but then would get a message that receiver cannot connect to the store. This had me stumped for a long while until I re-read this Carl Stalhood article (his blog posts are amazing!) and came across this bit:

If you have multiple Gateways, select one of them as the Default appliance. Note: when you point Receiver to a NetScaler Gateway URL for Discovery, after Discovery is complete, the Default appliance selected here is the Gateway that Receiver uses. In other words, Receiver ignores the Gateway you entered during discovery.

That bit in italics was what was messing up my configuration. As part of testing the deployment we had a separate internal gateway, and that was the current default. So when using receiver self-service that internal gateway was being selected and things broke.

A bit more info on the same from this Citrix blog post:

For web browser-based access, the “default appliance” setting has no impact.

For native Receiver access, this setting is downloaded to Receiver on connection to the Store as part of the Store configuration and that Gateway is used thereafter by default.

If all defined Gateways share the same URL via GSLB, then again, this has no impact (Receiver just uses that Gateway definition to see which URL to query). If the Gateways have different FQDNs and you enable them all for a Store, then whichever one is defined as the default will be used by all Receiver clients on first connect. This is problematic if you have two distinct user communities using different FQDNs that you want to aggregate into the same Store (for management simplicity) and they are using Receiver clients. For example, if you have https://myaps.company.com and https://myvdi.company.com and the Gateway selected as the default for the Store is “myapps.” Any user that enters “myvdi” into Receiver during first time setup will be re-routed to “myapps” as soon as they hit StoreFront and be prompted to authenticate again. The cleanest way therefore to deal with multiple Gateway FQDNs and native Receiver clients is via distinct Stores or via distinct StoreFront server groups. Again, fairly specific scenario, but this is another setting that we find is not very well understood by the field.

## Schedule Machine Catalog updates with MCS

I wasn’t aware of this until yesterday when I took a leap of faith and tried it out. I had to update my Machine Catalog with a new image but in the last step of the update my two options are to either reboot all my VMs now and update them, or wait for the next shutdown. The latter is what I want but I don’t have the Citrix Connector for SCCM (nor do my VMs have SCCM agent installed on them).

My delivery groups are set to reboot every weekend and since that was a few hours after I was doing the update above, I chose to go with updating on next shutdown. Then I took a look today and sure enough when the machines rebooted they picked up the new image. Nice!

Anyways, turns out this is well known info. Found this forum post where someone confirms this, as well as a blog post on how someone’s scripted this. Looks like this only happens if you reboot the VMs from Citrix. So a reboot from within Windows (or whatever OS you are running) won’t update. It has to be initiated from Citrix.

## Launching XenApp sessions in the receiver time zone

Gotta do two things for this to happen.

1. In the Delivery Controller policies enable this setting –

2. In the GPOs on the XenApp servers allow time zone redirection –

## [Aside] XenApp beta testing with Application Groups

Application Groups is a new feature introduced in XenApp and XenDesktop 7.9 (speaking of which: XenApp and XenDesktop are the same thing just that different functionality is exposed based on the license. I kind of knew this, but thanks to proper testing by James Rankin as shown in his YouTube video I can now say this with confidence). I’d thought of writing a blog post on this but (a) I am lazy and (b) this blog post from Citrix explains it much better. Take note of the example they give with beta testers – that’s just what I do in my environment too.

Machine Catalogs contain your machines. Delivery Groups target a subset (or entirety) of the machines in a Machine Catalog. Delivery Groups can contain machines from multiple Machine Catalogs but a single machine can only be a member of one Delivery Group.

Typically you’d create Machine Catalogs and assign machines from these to a Delivery Group. Then you’d define applications in the Delivery Group and assign users who can access them. When you use Application Groups, however, you continue to assign users in Delivery Groups but now you associate the Application Group with one or more Delivery Groups and define applications in the Application Group. You can set priorities for the Delivery Groups within an Application Group, and if an application is present in more than one Delivery Group (and the user launching the application has permissions to these Delivery Groups) then it is launched from the Delivery Group with the higher priority (a lower number has higher priority).

Once we start using Application Groups there’s no need to define applications in Delivery Groups.

Application Groups also help in targeting specific machines in a Delivery Group. As I mentioned above a Delivery Group can contain machines from multiple Catalogs. Using Application Groups its possible that some users are “pinned” to applications from machines in specific Machine Catalogs.

Here are more links on how Application Groups can be used along with tags:

## Adding Registry keys to NTUSER.DAT for multiple users

A while ago I had pointed to a blog post I found wherein the author wrote a script to push registry keys to the NTUSER.DAT profile file of a large number of users. I wanted to try something similar in my own environment and while I didn’t go with the script I found I made up something quick and dirty of my own. I know it isn’t as thorough as the one from that blog post (so I’ll link to it again) but it serves my need. :)

So here’s the deal. I have a bunch of profiles located at “\\path\to\profiles\ctxprofiles\$“. It has both v4 and v6 profiles. I’d only like to target the v4 profiles, and that too a specific user for testing. This user’s name contains the word “CtxTest” so I match against it. (Post testing I can remove the pipeline and target everyone).

All I do is get the list of folders, and for each of them load the NTUSER.DAT file from the correct location (it’s under a folder called UPM_Profile as I am using Citrix UPM). I just use the REG commands to load the registry hive, import a registry file, and unload the hive. Easy peasy. No error checking etc. so like I said it’s not as great a script as it can be.

## [Aside] How to roam AppData\Local too

Came across this video from James Rankin. Apart from being an excellent video, it has one important thing which I felt I must note down here as a reference to myself. I always thought AppData\Local and AppData\LocalLow were not synced as part of your roaming profile because they were special in some way. Today I realized that there’s nothing special about them. They are not synced because of a key called ExcludeProfileDirs in HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Winlogon. Any folder mentioned there is not synced as part of your roaming profile. Nice!

So to make AppData\Local roam, simply remove it from that registry key. Then selectively add any sub-folders you might want to exclude.

## XenApp and Run/ RunOnce keys

Reminder to myself: the Run and RunOnce entries in HKLM and HKCU are not processed if an application is launched via XenApp. That’s because these keys are processed by explorer.exe and that doesn’t run when you launch single applications (as opposed to the desktop).

## Set 7-Zip as the default for zip files

Had to do this for my XenApp install (7-Zip on a Server 2012R2). Thanks to this post which is in turn based on this post. Trick is to put the following into a registry file and double click/ import it on the machine:

After this go to Control Panel > Default Programs and 7-Zip will appear there. You can set it as the default for all extensions/ choose the ones you want.

Update: Frustratingly, I learnt that the Control Panel way doesn’t do the trick for Citrix. Later I learnt that maybe HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExts\ might be where FTAs (file type associations) are stored, so spent some time exporting the keys from there and pushing out via GPO. Turns out that didn’t do the trick either as it includes a hash tying the file type association to the user & machine where it was set to (bummer eh!). Thanks to these two posts [1][2] I learnt that the official approach is to use DISM to export the FTAs for a user and then deploy it via GPO. The FTAs are deployed to machines, so you can’t have per user customizations this way (but the two posts above have some workarounds).

The DISM command is: dism /online /Export-DefaultAppAssociations:c:\ftas.xml.

Update2: Here’s a blog post containing a tool that lets you bypass this hash issue.

Update3: This is a blog post about the OEMDefaultAssociations.xml. This is the file where the default customizations are stored, which you can over-ride via GPO. Or you could edit this file itself per machine. I learnt via trial and error – this file is very sensitive. If there are missing entries (the default ones) or even out of order entries it seems to be ignored altogether.

The entries in this are configured on new user profiles (existing ones are left untouched) and users can modify the associations if they want. The entries in the GPO cannot be changed by users.

## The Citrix Desktop Service failed to obtain a list of delivery controllers with which to register.

Funny little problem.

So I installed VDA 7.13 on a brand new Server 2016. Did the usual to create a catalog etc. But the VM doesn’t register with the Delivery Controller. Application event logs are filled with messages like these:

I am not looking to AD etc. for the list of Delivery Controllers, so why this error? Open up regedit and HKEY_LOCAL_MACHINE\SOFTWARE\Citrix\VirtualDesktopAgent\ListOfDDCs has the correct names too. So what gives?!

Turns out when I put in the Delivery Controllers name here I had set them as “DC1.fqdn. DC2.fqdn.“. I could ping either of these and connect to the ports etc from the VM, but just on a hunch I removed the “.” in the “fqdn.” and tada! it began working. :)

Moral of the story: Citrix Desktop Service expects Delivery Controllers to be of format “DC1.fqdn DC2.fqdn“. If it sees a dot it ignores the ListOfDDCs key and looks towards AD. It doesn’t tell you that it’s ignoring the registry key, so you are stuck wondering why it’s looking towards AD. :)

## [Aside] Always offline mode for cached files

I wasn’t aware of this until a few weeks ago. Starting with Windows 8/ Server 2012 there’s an always offline mode for cached files and folders. That’s useful!

## [Aside] NetScaler and WireShark

FYI to myself: NetScaler + WireShark. Lots of useful WireShark tips and tweaks.

## [Aside] Profile Manager NTUSER.DAT editing

I liked this blog post. That’s something I had thought of trying earlier when I was thinking about registry keys and applying them via GPP vs other methods. For now I am applying a huge bunch of my registry keys via the default profile and if there’s any subsequent changes then I’ll push the change out via GPP (for existing users) and also modify the default profile (for new users). But the geeky method the author followed of loading each user’s NTUSER.DAT and modifying the registry key directly is fun and something I had considered. Only catch though is that this has to be done during a period no users are logged in. Coz of this I don’t think I’ll be trying this in my environment but I liked the idea.

## Citrix – Word could not create the work file

I came across the problem outlined in this blog in our Citrix environment. It’s only got two test users (one of whom is me) and it only happened once to either of us, so I am not sure if it’s really the same thing or not.

The author’s findings are that it is because the %USERPROFILE%\AppData\Local\Microsoft\Windows\INetCache folder is missing. In my case the folder was present when I took a look, but maybe it got created – I dunno. The odd thing in my case was that I was trying to launch both Outlook and Word together and that’s when Word complained. Once I Word opened after Outlook had launched, it was fine. Also, oddly, this wasn’t the first time I had launched Word either. Previous attempts had worked fine.

What I did for now is add the above path to UPM to be synchronized. Hoping that helps. Else I’ll make a GPP like the author has suggested.