Writing Installs With The Windows Installer Is A Pain!

For the first time since the Microsoft Windows Installer has been around, I have had to write a “real” install for the small startup company that I am working at. What I mean by “real” install is one that customers who purchase our product or install it for demos will actually use. I am starting this tale a week into my ordeal. While I might talk a lot about the shortcomings of the Windows Installer here, you might learn a few tricks too.

Since I am one of the very first users of Wise, I decided to use the latest copy that I have from them (since they were bought out by another company, I cannot get a hold of any newer versions) called Wise for Visual Studio .NET.  I did not want to use the installer that comes with Visual Studio .NET since I knew I would quickly run into issues with it.

Requirements

Both Wise and VS.NET will do a simple install your files and features with no issues. Wise has many more built in features than VS.NET has. However, my install has some additional requirements that I think are not that outrageous and should be simple to do. Here they are:

  • Edit a web.config and app.config file.
  • Install a SQL Server database.
  • Install IIS if it is not installed (okay, this is a big one). Warn the user this is about to happen and allow them to back out of the install.
  • Display a dialog based on a feature that the user has chosen.
  • Create a virtual directory in IIS.
  • Only install on Windows XP and Windows 2003.
  • Create a directory and set permissions.

Except for automatically installing IIS, I do not think any of these things should be that difficult. To me, they are just normal tasks that any normal .NET application needs to perform these days. Well none of these tasks is easy with the Windows Installer/Wise. Before I continue, I need to say that the Windows Installer team has taken something that is not that difficult and have made it horribly complicated and hard to understand and even harder to test and debug. While Wise helped in some of the tasks above, I believe that the real problem lies in the lack of robustness in the Windows Installer. I come from the old Wise Installer days that use a top down scripting way of doing things. After working with the Windows Installer for a week now, I wish it were more like that.

What the Windows Installer Can Do?

One of the requirements is that our application can only run on Windows XP or Windows 2003. The Windows Installer can check for these system requirements but in a very limited way. I can set it to say it does not support any version of Windows before XP (good), but when it comes to the Windows NT versions, it can either check for all or one specific version (bad). Therefore, unless I write some custom script later, I cannot say “Requires Windows XP or Windows 2003”. All the other system requirements work in the same way.

Update: It turns out you can check for specific Windows versions with the installer (just not with the Wise IDE), but it is very confusing. After reading some of the Apress book listed at the end of this article I found out that installer properties can be Boolean or hold an actual value!?!? Okay, I have never heard of this before. Here is an example:

If you want to see if the user is running some version of Windows NT, you can use this:

NOT VersionNT

If you want to check to see if the user is running Windows XP or higher, you would use this:

VersionNT >= 501

As I am writing this, I am struggling with displaying a dialog that gathers information about a database server (server name, user name and password) so that it will only display after the Select Feature dialog if a certain feature was selected. This basically boils down to using Windows Installer events (discussed more in the “Wise or not so Wise” below).

Editing Files

Okay, this to me is a no brainer, most installs needs to edit files like web.config files, log files etc. Well, the Windows Installer does not have this capability!?!?! You have to write an external DLL or EXE to do this (which is not easy if you want to get information from the installer) or in my case, I used the Wise Script Editor (which complies to an outside EXE). While the Wise scripting worked, it was not elegant. I wanted to take a value in my web.config file like “{dbserver}” and just replace it with the real database server name gathered from the user during the install. Well you cannot…. the (Wise) script only has the ability to replace an entire line of text in a file.

Another issue with editing installed files is when to do it! With the old scripting version of Wise, it was easy, you knew when the file was installed and you then could edit it. Well, the Windows Installer does not work like that. It has these different areas called “Interface”, “Immediate” and “Deferred”. Furthermore, in these areas it has calls that is makes like MoveFiles, InstallFiles, InstallFinalize and more. So at first glance, you would just implement the editing EXE after InstallFiles… right? Wrong! In the install script, InstallFiles is not actually executed until InstallFinalize is called. Actually, everything in the script between InstallInitialize and InstallFinalize actually is queued up and run when InstallFinalize is called. Very confusing. I am still trying to understand when the Immediate and Deferred calls are run. I also found out that some of the properties (internal variables) are not available at certain places, like in Deferred. Dang!

Installing SQL Server Database

The Windows Installer cannot install (run) SQL scripts to create a SQL Server database. Wise dose have a very cool feature called “SQL Server Scripts” that will not only run scripts for your but it will even recreated a database, data and all! This saved me a ton of time.

Install IIS

Here is the big requirement and I did not think that any install program would do this and I was correct. It took me awhile to figure out how to force an install of IIS but I did right before I gave up. To do the install, the Microsoft Unattended Install program (sysocmgr.exe) needs to be called. Simply call it from the install like this:

sysocmgr /i:%windir%infsysoc.inf /u:c:iis.txt /x

The iis.txt file (that you create and install) should look something like this:

[Components]
iis_common = on
iis_inetmgr = on
iis_www = on
iis_ftp = off
iis_htmla = on

There is more information about sysocmgr.exe and the format of this file on the Microsoft web site. The iis.txt file format above is for IIS 5.0. Here is the format for IIS 6.0:

[Components]
iis_common = ON
iis_inetmgr = ON
iis_www = ON
fp_extensions = OFF
iis_ftp = OFF
aspnet= ON

There is another thing to worry about after IIS is installed. If the .NET framework is already installed, then none of the mappings in IIS for .NET pages like .aspx, .asmx etc. will be there. Therefore your ASP.NET applications and web services will not work.

To create the mappings the aspnet_regiis.exe program will need to be used (which is located in the latest version of .NET framework directory). However, this is not as easy as you might think. First, you need to figure out where the latest version of .NET is installed. This is the issue. There is a registry key called:

HKEY_LOCAL_MACHINESOFTWAREMicrosoft.NETFramework
Value Name: InstallRoot

Which will bring back “C:WINDOWSMicrosoft.NETFramework”. From there it is difficult from the registry to figure out what is the latest version that is installed. I just gave up (for now) and hard coded it to the version of the framework we are supporting (v1.1.4322). (If anyone knows of a better way, please let me know)

Call aspnet_regiis.exe like this:

C:WINDOWSMicrosoft.NETFrameworkv1.1.4322aspnet_regiis.exe -s W3SVC/1/ROOT/MyWebService

This “-s” switch will make the mappings only for the specified web site (I like this switch because this does not mess with other web sites that could have different mappings). The second parameter is of course the path to the web site.

Another thing to worry about is that with IIS 6.0, due to security reasons ASP.NET page extensions are not enabled by default. The only way I could find to do this automatically is with this VB script:

Set IIsWebServiceObj = GetObject("IIS://localhost/W3SVC")
' Enable ASP.NET
IIsWebServiceObj.EnableWebServiceExtension "ASP.NET v1.1.4322"
IIsWebServiceObj.SetInfo

Now that I have listed all the gotcha’s, the order in which these are done (as I have found out the hard way) is very important. Here they are:

1. Right before CreateFolders in the Execute Immediate section

a. Install IIS.

b. Also run aspnet_regiis.exe with the “-ir” switch (this was very critical for our install because during CreateFolders a folder is created that the ASPNET user is given access too. If aspnet_regiis.exe is not run, then this user could not exist on the machine!)

2. After your virtual directories are created in the Execute Deferred section

a. Run the VB Script that enables the ASP.NET page extensions in IIS 6.0.
b. Then run aspnet_regiis.exe as described above so that the ASP.NET pages are mapped to your web application.

Interact With The User/ Display A Dialog

As you have read, I need to install IIS if it is not there already. In the actual wsi script, I wanted to display a yes/no message box to make sure the user wants to install IIS. Well you cannot do this in the Windows Installer (not from what I could figure out). The Windows Install can display a message, but that is it. Again, I looked to the Wise Script for help. It can display yes/not message boxes and use that as the beginning of an “if” statement. Score! Well this would not work… I wanted to give the user the ability to abort the installation (because without IIS the feature they selected would not work). The problem is that the Wise Script cannot return to the install an exit code that would abort the install.

Create A Virtual Directory In IIS

Again, the Windows Install does not have the capability to create a virtual directory in IIS. Wise does and it works great.

Create A Directory And Set Permissions

While this was not easy to find in Wise, the Windows Installer can do this. It took a learning curve to get it right because the Wise documentation was not that good and an article on their web site told me to do the wrong thing. I only got it to work after a support call to them.

Wise Or Not So Wise

Now lets talk a but about Wise for Visual Studio .NET. While it has features that the Visual Studio install does not, over all it is flaky and difficult to use (if you are doing any type of custom install). One of the things that makes Wise hard to use is their lack of documentation. While it does come with a reference manual and a help file, both are severely lacking in details and “how to’s” and there literally no samples on how to do the tasks in Wise. It took me awhile to figure out the only way to get to the help file is via a dialog box… there is no way to “browse” the help file if you want to just look around and get familiar with the product. Speaking of samples, Wise does not come with any sample projects or sample scripts to help you get started. It only comes with two tutorials in one of the included PDF’s. So, if you want help on how to write VBScript files or .NET projects to interact with your install, forget it. Their help file also includes many links to the Windows Install SDK help file, which did not work even after I installed the SDK.

Unfortunately, as long as Wise has been around their documentation has not been very good. They do have a knowledgebase up on their web site, but you have to be a registered user to even use it and it is not much better than their help files. I actually found an article that told me to do something the wrong way (which caused a support call to Wise).

Now let’s talk more about why Wise is flaky. Here is an example: Sometimes it takes three or more tries (or the planets align) to add a script from the Wise Script Editor to get it to work. It never seems to work on the first try. I usually add the script… nothing happens when I run the install. Then I add it again and I get a memory error when run from the install. Then I add it again and I get another error that the program cannot be run. Then, if I am lucky the forth try (or more) it will just magically start working! There seems to be no rhyme or reason.

Setting and creating dialog boxes in Wise is very difficult. What makes it so difficult if you want to move the dialog box to a different place in the sequence during the install. Basically, you can’t. One time I just deleted the dialog, added a new one and Wise totally screwed up the dialog sequences some how. I kept getting a “loop” error and I could not figure out why. I just had to start over and create an entirely new install.

Also when adding and removing dialogs, I have found out the hard way that to move from forward and backward through the dialogs it all has to be set up in Windows Install events. You would think that Wise would help you out when adding and removing dialogs and add these events so the dialogs will appear correctly. Well Wise tries (I think) but does a very poor job. You will have to learn all about events (not as easy as you might think) and fix them on your own. It took me about half a day or more of messing with the events and conditions and testing to fix what I figured Wise should have done.

To get support with Wise and you are the registered user, you can log “Support Calls” on their web site, which are just really logging a question to their database. When you log a question, it says they will get back to you within three days! Well the good news is that they usually got back to me in one day or a little longer. The bad part is that I had to log seven of these support calls to finish my install requirements listed above.

Summary

Therefore, to end this long list of complaints on the Windows Installer and Wise, I just hope that the new version of Wise is better and comes with better documentation. I also hope that the Windows Installer starts coming out with more features and their SDK documentation get easier to read and understand. I’m fearful on what how much more difficult it will be when Longhorn is released. I just bought a book from Apress titled “The Definitive Guide to Windows Install” that I hope will help me understand more about the Windows Installer. In addition, I am completely surprised about the lack of information on the web on this subject. I Google’d for many, many hours and did not find much of any inforatmion, especially on interacting with the installer during runtime with VBScript or .NET. I did find a web site that seems like it might be of some help: http://www.installsite.org/. In addition, I found some help on the Microsoft newsgroup located at: http://msdn.microsoft.com/newsgroups/default.aspx?dg=microsoft.public.platformsdk.msi. If you have any comments of suggestions on the article, please let me know!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: