Skip to main content

WiX Installer Phantom Overwriting App Settings for New Users

Recently I received a bug report of some very odd behavior in a Windows application that my team and I had written. Sometimes the server URL, which was set during the application's installation, would be overwritten to the default value of http://localhost.

The application in question is a WPF application. I have kept up with the latest libraries and framework updates. It is installed with the WiX Toolkit 3.9, so even that is current.

When you have a problem that happens "sometimes," the first thing you need to do is figure out what "sometimes" means. My first thought was to check the value in the app.config file. It had indeed changed, which was odd, because the application cannot change values in that file using the Properties.Settings API. It would actually be a compiler error to try.

I checked the source code anyway, to see if someone had brute-forced their way around that limitation using the XML APIs. Nope. It wasn't that.

The next thing I checked was the modification time of the app.config file itself. I asked the user who reported the issue, let's call him John, to uninstall and reinstall and give me me the timestamps on all of the files in the Program Files folder for the application. Then we waited for the problem to recur. Fortunately, that didn't take too long. The next day I got an email from John that went something like this...
Mike, this morning when I came in, Bob was complaining that the URL had reset.
What? Who? Bob complained? Who is Bob? I thought this was John's computer. As it turns out, it's a shared PC in a common location, and multiple log onto it and use my application. Now we're getting somewhere.

I asked John to find out approximately when Bob logged on and noticed the issue, to send me a copy of the app.config file, and to provide me the same time stamps on the rest of the files in the application's folder. John came back and said it was right after lunch. Lo and behold, the app.config file had been modified at roughly the same time Bob was said to have logged on. Opening the file John had sent me, it was clear that all of the configuration settings (not just the server URL) had been reset to default. It was only the Server URL that was dramatically noticable, because http://localhost wasn't valid for their installation. Somehow, I inferred, the WiX installer was running again for Bob when he logged in, even though the application was already installed for "all users."

So now I had something concrete to go on. Firing up my Windows Azure development VM (every developer has one of these, right?), I created a second user account that I could use to test my new theory. I logged in as myself and installed the application, specifying a non-default value for the server URL. Then I logged out and back in as the new user. To my surprise, the app.config file had indeed been modified, and all values were reset.

My next stop was to the Windows event logs. This is what I saw:
  1. Detection of product '{658A4A3C-0C54-4874-BC0D-EAD6140C6938}', feature 'ProductFeature', component '{87D14857-5683-5A5D-BB43-27C83156DC14}' failed.  The resource 'HKEY_CURRENT_USER\Software\WalkingRiver\My App\' does not exist.
  2. Detection of product '{658A4A3C-0C54-4874-BC0D-EAD6140C6938}', feature 'ProductFeature' failed during request for component '{C5F530F6-29D1-5BE4-897D-910309F2C649}'
  3. Beginning a Windows Installer transaction: {658A4A3C-0C54-4874-BC0D-EAD6140C6938}. Client Process Id: 19300.
  4. Windows Installer reconfigured the product. Product Name: My App. Product Version: 1.7.1208. Product Language: 1033. Manufacturer: WalkingRiver. Reconfiguration success or error status: 0.
  5. Product: My App -- Configuration completed successfully.
  6. Ending a Windows Installer transaction: {658A4A3C-0C54-4874-BC0D-EAD6140C6938}. Client Process Id: 19300.
Near the top of the Application Event Log were the above sequence of messages from MsiExec (the Windows Installer) that said a part of my application was not found. Looking closely, I see that the installer is looking for a registry entry under HKEY_CURRENT_USER (HKCU). When it failed to find that entry, it assumed the installation was broken and needed be repaired. Re-running the installer in quiet mode (no UI), forced the app.config file to be replaced with no input from the user. Thus, all of the default values were replaced.

That answered the question of how, and partially the question of why. But why is the installer looking for a registry setting under HKCU for an application installed for "all users?" To answer that question, I had to open my WiX source code and see if I could find out. It didn't take long. In my product.wxs file, I found this:

Notice that RegistryValue tag, with Root="HKCU". This was the culprit. Even though the installer was installing the application for all users, it was setting a user-level registry entry as proof of installation for the application's shortcuts. Looking at the WiX documentation for creating shortcuts, shows that this is the preferred way of doing this.

A quick search led me to a possible solution here. Apparently, I the correct value to use is "HKMU." This will automatically resolve to "HKCU" if the application is installed "per user," or "HKLM" if the it is installed "per machine."

I quickly changed the value, rebuilt my installer, and ran my test again. When I installed the application under my own account, entering a non-default value for the Server URL, things seemed to go OK. I cleared the Windows Application event log, logged out, and then back in as my new user account.

Checking the event log, there were no messages at all from MsiExec. Then I checked the app.config file, and found that its values were those I entered during the installation. Success!

I sent the new installer to John, who reported no further issues. Whew!

Windows is a multi-user system, although not everyone creates more than one user account. In fact, I don't often have more than one account on my development machine. It wasn't likely that I would ever stumble upon this bizarre issue, especially since the WiX installer examples all show HKCU for their registry values. However, my application was run in an enterprise environment, on a shared computer, on an Active Directory network.

The moral of this story is to try to develop and test your applications in an environment that is as close as possible to your end users'.


Popular posts from this blog

How to copy your Frozen Free Fall progress to a new phone

It's happened to all of us. You are about to get a branch new smartphone, when it hits you. You're on level 250 of Frozen Free Fall. If you get a new phone, you'll lose all of that progress! Ok, admittedly this isn't the most pressing problem of our time, but it's annoying. So today I decided to do something about it.

I have a Samsung Galaxy S4 (Android), and just received an iPhone 5c. Before you bash me on my phone choice, let me explain that the iPhone is provided by my employer at no cost to me. Now you may proceed to bash me for putting games on my work phone. 
First step: Frozen Free Fall had already been installed on both devices. Next, using the Astro File Manager on my Galaxy, I searched and found the Frozen game save stored in /storage/sdcard0/Android/data/com.disney.frozensaga_goo/files/user.dat. I imagine it will be in the same location on any Android phone. If not, just look for user.dat in a folder with a similar name. So, using a USB cable and the A…

Ionic vs. Bootstrap - for a Web App

Ionic 1.x vs Bootstrap 3.x for a Web AppI was recently asked at work to come up with a comparison between Ionic Framework and a more traditional Angular/Bootstrap combination to create a web app. The application will primarily be used in a desktop web browser (probably Chrome or IE). There are also some use cases where it will be accessed from Safari on an iPad. However, this is purely a web; there are no plans to install the app onto the iPad as a hybrid app. Thus, recommending Ionic to build the UI hadn't occurred to me until the request was made.

This is even more surprising in that I recently published a Pluralsight course on Ionic Framework 1. It should have been the first thing that crossed my mind.
One constraint is that currently only Angular 1.x and Bootstrap 3 are authorized web technologies. Ionic 1.3 was recently approved, but not Ionic 2, Angular 2, or TypeScript yet.
Given those constraints, herein is my attempt at coming up with reasons to use (or not to use) Ionic…

Record Video of Your Android Screen on a Mac with ADB

Background I've been working a lot lately on writing mobile apps using the Ionic Framework. My goal is to be able to release apps for both iPhone and Android at roughly the same time. So far, I've only released apps for Android, simply because I'm too cheap to pay Apple $99/year. But that's neither here nor there.

The Problem Today I wanted to record a demo video for one of my apps running on my Android test device, an older Samsung Galaxy S4. I had no idea how to do that. Camtasia 2 for the Mac supports iOS devices out of the box, but not Android. What to do?

After a bit of searching, I found instructions on a few different sites. None of them had all of the steps I needed. So rather than trying to remember where I found everything, I figured I'd put all of the instructions in one place on my own blog so I could find it again easily.
PrerequisitesAndroid Debugging Bridge or Android SDKUSB to Micro USB cable (preferably the one that came with the device). Record t…