Windows Installer Dilemma

My current task is to create an installer. The dilemma: Visual Studio doesn’t provide a very robust Setup and Deployment project.

The options?
1. Create a WiX Project
2. Write a bootstrapper/custom GUI/etc. and P/Invoke msi.dll
3. InstallShield ($$$)
4. Wise ($$$)
5. Nullsoft Scriptable Install System

Here’s what I’ve run into. WiX is pretty straight-forward and configurable. It is also open source, so you are able to rewrite the user-interfaces to fit your needs. The only thing is that the whole project is in XML, which means creating a dialog means setting values for buttons, labels, and textboxes manually. I’ve thought about writing a short program to create the dialogs for me, which I may still do. The problem I’ve found with WiX: I can’t figure out how to refer to code (Assembly Info). I have found two possibilities: replace WiX version via PowerShell script and using MSBuild tasks. However, my development team wants to make the project as simple as possible. Using WiX already means that everyone will have to install WiX in order to build the file properly. This will only be a problem until the next version of Visual Studio, which is supposed to ship with WiX installed.

Option 2 is one that I got from Rick Brewster, of Paint.NET fame. Well, not directly from him. Scott Hanselman has an excellent podcast which details the Paint.NET installer. It is beautiful in it’s simplicity. I’ll leave a few things out, to tailor it to my discussion.

I’ll start from the outside-in.

  1. The installer comes as an executable created by NSIS (#5 above). This installer basically acts as a zip file, which extracts the contents to the user’s application folder and runs the bootstrapper.
  2. The bootstrapper checks for the proper version of Windows, and .NET
  3. If the requirements .NET aren’t met, the .NET redistributable installer can be run from the directory.
  4. When everything is good, a custom GUI setup program runs.
  5. The program gathers necessary information, injecting it into the MSI installer which is actually the same one created by Visual Studio.
  6. Then, any number of MSI installers can be run.

This method of staging, bootstrapping, gathering, and then running seems the most efficient. The problem is that the whole MSI interoperability means having a full understanding of Windows Installer technology. It is possible, however, to simplify this even further. On the progress form, use msiexec and switches. Because I’m not that interested in fully understanding the Windows Installer technology at the moment, this option is a little more than I want to get into. But, I have actually started a project that uses a very similar method.

InstallShield and Wise cost money, so they are not options for me.

NSIS is another excellent option. The only problem I see with it is that it’s like learning another scripting language. Although it is very simple, it doesn’t particularly appeal to me. XML, however, does.

So, it looks like I’m going to go with WiX as my choice to create an installer.

.NET development

I consider myself a .NET developer. I don’t consider myself good at it. There are always things to learn, and new facets of development that I didn’t realize existed.

I plan on keeping this blog as a way to keep tabs on what I’ve been doing. I am currently working at Agility Healthcare Solutions, on a Rich Internet Application used to track patients, staff, equipment, and beds in a hospital environment using RFID.

The language of choice is C#. Be sure to check back regularly, maybe you’ll find something of use.

C# Insertion Sorting alrgorithm.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
 
namespace InsertionSorting
{
    class Program
    {
         static void Main(string[] args)
         {
             // int[] A = {5, 2, 4, 6, 1, 3};
             int initializer = 100000;
             int[] A = new int[initializer];
  
             for (int my = 0; my < A.Length; my++)
             {
                 A[my] = my;
             }
  
             // Random shuffle
             Random rand = new Random();
             for (int k = 0; k < A.Length; k++)
             {
                 int firstInt = A[k];
                 int swapIndex = rand.Next(initializer);
                 int secondInt = A[swapIndex];
  
                 A[k] = secondInt;
                 A[swapIndex] = firstInt;
             }
             
             //Console.Write("Array before sorting: ");
             //foreach (int number in A)
             //{
             //    Console.Write("{0} ", number);
             //}
             //Console.WriteLine("");
  
             int index;
             int j;
             int i;
  
             Console.Write("Insertion Sorting array of {0} numbers, please wait...", initializer);
             
             DateTime start = DateTime.Now;
             for (i = 1; i < A.Length; i++)
             {
                 index = A[i];
                 j = i;
  
                 while (j > 0 && A[j - 1] > index)
                 {                    
                     A[j] = A[j-1];
                     j--;
                 };
                 
                 A[j] = index;
             }
             DateTime finish = DateTime.Now;
             
             //Console.Write("Array after sorting: ");
             //foreach (int number in A)
             //{
             //    Console.Write("{0} ", number);
             //}
  
             Console.WriteLine("");
             Console.WriteLine("Duration: {0} seconds", (finish - start).ToString());
         }
     }
 }

Developer James Schubert shares his code and his thoughts.