With the advent of 64-bit hardware, Microsoft has released a 64-bit version of Windows to leverage the capabilities of these hardware platforms. The new Version has the advantages of addressing more than 4 GB of memory, being more responsive and providing better security.
64-bit Windows is backwards compatible to some degree, meaning that most 32-bit applications can run normally on it. But software companies that wish to take full advantage of 64-bit either have to make a few changes to their products or rebuild them. This leads to two versions of the same product: one for each Windows platform.
Managed applications can run in 32-bit and 64-bit environments given that they are compiled at the last minute on the target platform by the Just-In-Time (JIT) compiler. However, the deployment on both environments requires two different installers.
In this blog, we show how to build and package a managed application in a platform-agnostic way. This will enable it to run on any Windows platform, and companies will end up maintaining only one version of their product.
We start by discussing GPO deployment and target deployment environments. Then we show how to build the product’s source. Next, we introduce WiX and discuss how we used it to package our application, and finally, we explain a deployment issue we faced and how we went about solving it.
Group Policy Object (GPO)
GPO stands for Group Policy Object, a tool of the Microsoft Windows NT family of operating systems. Through GPO, a set of control rules can be enforced on Windows user accounts and computer accounts. In other words, GPO specifies what users can and cannot do on a computer system.
In the Windows world, many enterprises rely on GPO to deploy their applications. Administrators can deploy software packages to any number of end systems, and these deployments will take place according to the settings the administrators specify.
GPO clients pull and apply the policy settings appropriate to the machine and user. Some settings require a reboot and/or user logon, such as software installation.
GPO is good at managing a heterogeneous environment of Windows systems. Such an environment may contain different versions of Windows.
The following figure shows a policy that is created under an organizational unit in Active Directory. The policy has an installer, and the policy specifies that the installer is user based.
Fig. 1: A per user installation set to be deployed through GPO.
Compiling a managed application to run on 32-bit and 64-bit environments
The software’s source code must be compiled for Any-CPU platform. As the name implies, this will result in assemblies that are independent from the target platform. In other words, this will make sure that resulting dynamic-link libraries (Dlls) and executables will run on both 32-bit and 64-bit Windows platforms.
Compiling for Any-CPU makes sure that Dlls and executables will be allowed access to all parts of the registry of the hosting operating system. This is very important as 32-bit applications deployed on a 64-bit Windows will be limited only to the Wow6432Node part of the registry; they won’t be able to read, write, or even detect the 64-bit part of the registry.
WiX installation technology
Many options are available for writing an installer, including NSIS, InstallShield, WiX, etc. Each technology has its pros and cons, but after looking into each one, we chose to use WiX.
WiX is a declarative XML based language that produces MSI installers when compiled, and has many advantages:
- It allows full access to Windows installer functionality including custom actions
- It is XML-based, so any editor can be used to write its source files which are easily source controlled
- It is free; there is no expensive licensing for dedicated tools
- It has been designed and maintained by Microsoft
- Its command-line interface allows it to be integrated into any automated application build process or continuous integration environment
- Its scripts are written in a way that makes it easy for developers to update the parts of a Wix script that is specific to a change they made
- It allows incremental updates, where only specific parts of the software are updated
- The deployed software is automatically registered with Add/Remove Programs
- It provides easy and proper installer versioning
In WiX, we can list the files we want to deploy, and their deployment locations. We list the registry keys to be created, and specify that they are per user keys. We also list the required prerequisites for our application to run. The installer is then built as a 32-bit installer.
The following sample shows what a WiX source file looks like:
<?xml version=“1.0” encoding=“UTF-8”?>
<Product Language=“1033” …>
<Package InstallerVersion=“100” Compressed=“yes” Manufacturer=”…” …/>
<Media Id=“1” Cabinet=“media1.cab” EmbedCab=“yes” />
<Directory Name=“Install Practice”>
<Component … />
<File Source=“InstallMe.txt” />
<RegistryValue Root=“HKCU” Key=“Software…” Value=”…” KeyPath=“yes” />
After the administrator creates the GPO per-user deployment policy, an end user logs in with his credentials on a system that is targeted by the aforementioned GPO policy. This launches the WiX installer: the user remains on the logon screen during installation, and once installation is finished, the logging in continues normally to display the desktop.
32-bit installers trying to install on a 64-bit target machine will be limited to accessing only the 32-bit parts of the registry. This is a problem for managed applications that expect their registry keys to be in the 64-bit parts of the registry, especially when they are hosted in a 64-bit application.
In our case, the 32-bit application failed to launch in its 64-bit host. After analysis, we found that the files were deployed to the correct location on disk, but the registry keys for the logged-in user were missing under 64-bit HKCU (HKey_Current_User). This prevented our application from being detected by its host.
To troubleshoot, we ran regedit as administrator while still logged in as the same user account and violà – the registry keys were there under HKCU. We realized that because our application was deployed using GPO per user, and GPO installs the application using an administrator’s identity, this resulted in our application’s HKCU registry keys being created only for the administrator, not for the user’s profile on the target system.
Creating custom registry keys
To solve this issue, we had to handle the creation of registry keys ourselves. We wrote a simple tool that creates them using the data to be stored and a Security Identifier (SID). The SID is a unique name assigned by a Windows Domain Controller during the logon process to identify a user.
To properly handle the registry keys, the tool creates them under HKU (HKey_Users) for the specified SID. The same keys will appear under HKCU for the logged-in user identified by the SID; this is because HKCU is merely a view of the registry keys for the current logged in user profile. This profile is stored under HKU along with all the other user profiles that logged in previously to the system, each with a unique SID. In this manner, the application’s registry keys would then be found under HKCU as expected.
This custom tool was integrated in the WiX installer. When deployed through GPO, the WiX installer is aware of the SID of the user that is logging on. Depending on the target platform, Wix will launch the tool, using a custom action as a 64-bit or 32-bit process. Wix passes the SID of the currently logged-in user. This allows the custom tool to create the registry keys for the proper user profile, and in the proper location of the registry.
We have shown how to build and package a managed application to run on both 32-bit and 64-bit Windows platforms. This results in one version of the application to maintain. The benefit is lower maintenance and development costs for the producers, and easy deployment and management for customers.
- WiX: A Developer’s Guide to Windows Installer XML, Nick Ramirez, PACKT 2010
Trackback from your site.