Monthly Archives: July 2010

InstallShield 2010 LE Bug Hell

I decided to play with InstallShield 2010 LE today and for the life of me I can’t even get it to build a simple MSI. Every time I try to build I get the error:

-5002: Product Configuration ‘Express’ is not found in the specified project. Verify that the Product Configuration name is correct.

This error message is useless because IS 2010 LE doesn’t allow you to edit such things as product configurations. Regardless I checked and it all seems to be there in both the GUI and ISProductConfiguration table. It just refuses to find it.

Then it became interesting. I double clicked on the error and was taken to the InstallShield KB search page. I selected Product and Version and low and behold Limited Edition wasn’t even a choice so I left it blank.

This is when I came upon Q109699: ERRDOC: Build Error 5002. I clicked on it and received the following error message:

The funny part is the name of the script: SuckerFish. Yes, I know this is a common web script but at this moment if feels like the universe is trying to tell me something:

Developers are nothing but fish to InstallShield and that they are suckers for trying IS 2010 LE.

Back To Basics – Installation Principles

I came across an old thread on StackOverflow lately where the following question was asked:

I’ve read a bunch of documentation on installers and haven’t come across anything good that explains the underlying concepts. Most of the installer software I’ve come across is based on the same “database” like structure that I just don’t understand at all.

All of the documentation that comes with the various products – i.e. WiX, InstallAware, Wise, InstallShield etc expect that you understand these underlying concepts [which I just don’t get] in order to follow what they’re talking about.

Can anyone point me in the direction of documentation that explains the concepts of software installers so that the software documentation actually makes sense?

– Bob The Builder

Bob makes a good point. Just how do you define a good install? After doing installs for 14 years, I sometimes forget that these principles aren’t understood by many or really documented anywhere except perhaps in dated books like Bullet Proof Installs by Leslie Easter. It’s mostly tribal knowledge. I have decided to make a short list of mostly generic recommendations that I’ve learned over the years.

1) Remember that your install is the very first impression the user gets of your application. If your install sucks or worse fails that will not want to use your software or your support desk will get flooded with calls. I can not understate this point. I have saved companies from the brink of bankruptcy by fixing their deployment problems and I’ve seen companies fail that were unwilling to take their problems seriously.

2) The install must be bullet proof. It must work on any kind of machine you throw at it. Keep It Simple and avoid anything that could be brittle. Know and follow all current windows platform best practices

3) Perform all of your checks, user inputs, validation up front. Prevent failures up front.

4) Have a clear point of no return. You should make no state changes prior to that point and there should be no user prompts after this point.

5) Avoid Reboots – e.g. Don’t settle for getting your service to start by performing a reboot

6) The installation should be transactional ; support rollback. We are all on or all off – no in between.

7) The installer must support silent installation including all settings that could be manipulated if running interactively.

8) Keep the UI Simple. People don’t read; they just press next. Let the defaults represent the general case.

9) Don’t step on other peoples software. Take care with regards to DLL hell when installing shared components.

10) You must have a safe uninstall that doesn’t break the system or ask the user scary questions like “do you want to remove these shared dll’s?” Dll what? is what your use will think.

11) Think ahead about servicing your application. You must be able to upgrades and patching ( your choice )

12) Always avoid rolling your own. Learn to use Windows Installer and follow all of it’s best practices.

Finally I have a personal mantra that I follow:

It’s not my machine, it’s my customers machine. DO NO EVIL.

1) Don’t change system settings. I once had a developer ask me to change the regional settings to make a report look better with no concern of the broader implications.

2) Don’t change the security posture of the machine. Don’t open up ACLs on directories or create service accounts with fixed passwords.

3) Don’t install ad-ware / malware. Sorry but no, I don’t want your damn Google / Yahoo! toolbar and so on. If you must, make it an opt-in not an opt-out and by damn don’t intentionally break your UI so that when the user says no you do it anyways.

4) Don’t be annoying with autoupdates. Make it an opt-in not an opt-out.

IsWiX 1.0.278.0 Available

My family is out of town visiting relatives in celebration of the good news we received: another clean CT scan! That makes 2 1/2 years since her last surgery and that’s a very good thing. I really wish I could have gone with her but next week I’ll be giving a WiX training session to about a dozen developers.

So being home all alone I decided to put some pen to paper ( metaphorically ) and knock out a features for IsWiX.

Document Directory MRU: IsWiX now remembers the directory of the last document you accessed and uses it as the default location for the file dialogs. This wasn’t a critical feature to me since I normally launch IsWiX via Votive but someone at work pointed this out to me as a nice to have feature so I took care of it.

Window Size / Location: IsWiX now remembers the window size and location. I noticed at work that most developers were repeatedly resizing their windows which didn’t seem very fun:

Custom Tables Designer: I’ve started work on a new designer for defining and populating custom tables. It’s only a stub at this point and thus I’ve set the IFireworksDesigner::IsValidContext() method to return false to hide it. Still, the assembly is getting built and deployed for future use. ( I love Agile Setup Driven Development! )

Properties Designer: I’ve created a new designer for defining Properties. It’s a straight forward DataGridView/DataSet that authors and sorts the Property elements after Dependency elements if they exist otherwise after the Package element. It also supports the ModularizationSuppress, Admin, Hidden and Secure attributes.

I’ve also made another observation: InstallShield 2010LE can consume Setup Prerequisites and Merge Modules. It’s restricted from doing other things like consume C++ DLL CA’s and execute SQL scripts but with a little creative authoring of merge modules, WiX can easily inject those abilities. Bottom line? I now have a pretty decent platform for authoring small yet complex installers including bootstrapping, chaining, websites, sql, services, xml updates, and custom actions. The draw back is pretty limited customization of the UI and the restriction of only supporting 1 feature per install. Can anyone say micropackage?

.NET Bitness Pain

One of the really cool things about .NET is the ability to write platform independent code. You can build an EXE as “AnyCPU” and on an x86 windows machine it will run as a 32bit process and on an x64 windows machine it will run as a 64bit process. It’s that simple; you don’t have to worry about ‘bitness’! Well, that’s the sales pitch anyways.

In practice I’m noticing it’s far from that simple, especially considering that Windows Installer cares very, very much about bitness. If your code uses less then 100% pure managed classes you will find yourself falling into a number of traps that are important for developers and setup developers to understand. Sadly I’ve yet to find a comprehensive list of these issues.

So let’s start with a simple example. Let’s go back 10 years in time and pretend we are writing an x86 application and x86 installer with no concern for x64. Someone hands you a vb6 EXE and a regfile ( HKLMSOFTWARECompanyProduct type entries ) and says this is what needs to be deployed. You go off and create an MSI that writes the registry values, deploys the EXE and creates a shortcut. Now let’s come back to present. You take that MSI and throw it on a modern Windows 7 x64 box and it works just fine.

But now let’s pretend that the EXE was a .NET application. If it was compiled as x86 it would behave the same way. But if that application was built as AnyCPU ( the default for all versions of Visual Studio prior to VS2010 ) we are going to land in one of those traps. Here’s why:

The MSI is marked as an x86 package so it writes the registry data to the Wow6432Node of the registry so the expected x86 application can find it. While the EXE gets installed to ProgramFiles(x86) it will actually JIT as a 64 bit process. This process will fail to find it’s registry resource at runtime and crash. This is because the .NET BCL Win32.Registry class cares about bitness.

These traps are all over the place. For example if you P/Invoke a C++ DLL you’ll need to have the correct x86 or x64 dll and the same goes for things in WinSxS and the GAC.

I recently read a .NET MVP blogging about these issues and he wrote a comment “to have the installer deploy both.”

There’s just one big problem with that: MSI doesn’t support that. The Windows Installer team seriously expects you to build two MSI’s for the two platforms. This goes against what the .NET team encourages.

This is a huge problem and I’m somewhat suprised that I’m not hearing more about it considering the huge uproar when Vista was released and the break neck speed x64 machines are entering the market.

I’m not sure exactly where to wrap this up other then I’m trying to gether up what all these traps are because most developers I speak with seem suprised when I mention this. Be sure to test your apps on both x86 and x64 to look for problems and seriously consider doing what Visual Studio has done: Compile your .NET apps for x86 instead of AnyCPU. I wouldn’t use Any CPU until you are really ready to support x86 and x64 deployments.