I received an interesting inquiry recently – we are writing applications specifically to be run under Citrix App Streaming and we want to make sure we don’t do things that will cause complications at runtime. Can you tell us what to avoid in programming so we can ensure that our applications work well with Citrix Application Streaming?
What a nice way to word this! Very positive. No negative thoughts about what you can’t handle, just a happy thought about proactive steps they should take to ensure the created applications will work well when they are run under App Streaming.
The mission here is to take advantage of the RADE aspects of App Streaming; a single place to update the application and have it automatically land on all the servers in the farm, with a single update to the Application Hub.
In this example, the virtualization aspects of App Streaming are much less important. Coding the applications specifically for this environment, the customer has absolutely no NEED for virtualization. They are quite capable of coding the application to not do stupid things like write to HKLM or \Program Files at runtime.
The inquiry goes deeper to ask, what things in Windows programming will give you headaches in application virtualization. We’re coding the applications now and we can avoid those, we just appreciate information on what should be avoided.
Here’s what I told them
DCOM. This actually works under App Streaming, but the arrangement of server and the client across isolation boundary is a complication because most applications are both servers and clients. If server is outside of isolation, the client will talk to server, but the server (as a client) will not be able to talk to client as a server. Recommendation: Use COM instead of DCOM, either inproc or out of proc, it doesn’t matter. Both work well under isolation and require precisely zero runtime configuration by an administrator.
NT Services. Again, these work, but they do require awareness in isolation and setting up of security aspects to tell the streaming system that it is okay to load services for that profile. Recommendation: Avoid services if you can, but it may not be possible. I mean, the whole reason for using services is to do things that you can’t do in user privilege, so they might need a service and if do, code it, but be aware that it will be an area that requires observation during profiling and configuration for runtime.
WinSxS. Often ‘C++’ applications created with Visual Studio automatically include “manifest data” which calls for a specific version of the C runtime be loaded at runtime. This can create headaches if that specific version is not locally installed on the machine. Recently, updates from Microsoft allow the “latest” runtime to be used even if the app requests an earlier version and this does well to make the problem go away, but the problem can be avoided by not putting that manifest data in there in the first place. Just leave it out! There are options in Visual Studio to do this. Or, statically link the runtime, but this wastes memory. Alternative, create your own DLL which is the runtime, but it is YOUR version of the runtime. This by the way isn’t exactly an App Virt statement; WinSxS is major headache isolated or not. I’ll save that for another day.
Getting onto more nitty gritty
Don’t store installation time USERNAME inside registry values and then expect that information to useful at runtime. YES – Applications do this.
If it’s already in HKCU, the username is redundant, but some applications store it anyway and this causes headaches at runtime because the profiling time HKCU is reflected into the isolation space HKCU – and the username won’t match. The App Streaming system doesn’t runtime “correct” these values. I hear some other systems DO, but we don’t, so if you are coding application, either for isolation or locally installed, if you need to know the user name at runtime, look it up at RUNTIME.
MACHINE NAME. Don’t store this either. If your program writes down the machine name into the registry as an installation activity, there is no guarantee that at runtime, the machine name will be what it was at profiling. Best practice, resolve the machine name at runtime, not at installation. YES, there are applications in the world that do this incorrectly, making it harder to run them on any virtualized environment, including XenApp, Provisioning Services, App Streaming. If you want to know the machine name, look it up and then throw away the answer when you’re done.
More installation time trouble – IP Address assumptions. DHCP has largely made this go away, but an application can ASSUME that there is an IP address for the USER. There isn’t, there’s an IP address for the MACHINE, or potentially multiple IP addresses for the machine, but the IP address itself is useless for communicating into the machine to talk to the user. This includes localhost. When an outsider opens a port on your machines IP address, remember that in a terminal services world, there will be multiple users running the same application at the same time and only one of them will have the port.
Getting it simpler
You know what, all this can be simplified to “don’t do anything at installation”. Figure EVERYTHING out at runtime and life is a happy place. If we could just get global COM registration to not be a requirement, there really aren’t many reasons for installers.
That’s about the summary I provided in response to the inquiry. In writing this, I have some more.
Starting to get out of my comfort zone, but in defining data sources, there are lots of ways to do it and they vary considerably for the database system (Oracle, MS SQL, IBM) and even by version of database “driver”. SOME APPS expect to configure this data as an administrator step outside of the application. That is, install the app, then go into data sources in the control panel, configure the database connection and then the application will work. With App Streaming, the control panel aspects either have to be set up really via the control panel on the execution system which defeats the idea of no local machine installation, or simulated into the application via other means including putting it into the profile installation image or setting it via script or other policy engine.
The easier answer: Have the application configuration settable by means that are easily adjustable from pre-launch scripts or via other streaming controlled mechanisms, including just doing it inside the profiler. Yes, you could have panels in the application itself to set this, but we’re assuming that users aren’t going to be doing this level of administration. So, configure it via pre-launch activity or global configuration.
HKCU Reflection vs. USERPROFILE reflection
Profiling time writes to HKCU are captured by the streaming profiler and these are “layered in” to the HKCU at runtime. For example, if the admin is named “joeadmin”, then the HKCU adjustments for joeadmin at profiling will “show up” in the joeuser view (notice username changed) of the registry where the USER is running the app. What happened at profiling appears to have also happened for the USER at application runtime. This by the way is one of the key items in reflecting COM registrations done in user space at install time into user space at runtime. Everything written to HKCU at profiling shows up as part of HKCU for the application at runtime under isolation.
Same thing is NOT TRUE for disk files
Yes, it could be true, but it isn’t. So, if you’re writing an application and intending to use it under App Streaming, don’t create this dependency.
The default rule sets don’t isolate USERPROFILE, so the install time stuff written to this space at profiling will be “gone” for user runtime. Now, this isn’t just an app streaming thing, it’s a Windows application thing. If administrator installs an app that writes files into the administrators user profile, these will not exist for users running the application, assuming the users are not the administrator.
Vista UAC dialogs have pretty much solved this for commercial applications. For custom applications, it’s something to be aware of and something to avoid in development. Side note is that anything omitted could be “added” into the installation image and it would then “show up” at runtime as expected. If you need to do this, copy the files into space either during profiling or via pre-launch script at runtime and you can configure anything that the application will want to see.
This post is another one of these “exposing your weakness” kinda posts. I hope the information is useful.