Creating an MSI Package for C# Windows Application Using a Visual Studio Setup Project

Introduction

There are many ways provided by Microsoft to create a setup project for Windows applications.

But when I started to create one, I got nothing but queries and confusion of how to start and where to start. There are numerous articles I found over the network, explaining how to create a setup project, but some do not work as they say, and some do not have a live example to follow.

The driving force for me to write this article is my QC team, who accepts the main application to test and verifies my setup installer with their 100% effort. And guess what, they were successful in finding bugs in that too.

In this article I would like to explain a step-by-step procedure to create a Windows application and a setup installer for it in a very simple manner, that is easy to understand and follow. There are many alternative ways to do it.

Start the Show

First let's create a simple one-form Windows application, having a text box and a button only.

The creation of the Windows application is just for the sake of having one to install.

MSI1.jpg

I gave the name CreatingInstaller to my Windows application, obviously you can have your own.

Thus adding a new Windows Form Application in my solution and adding a text box and button to the default form resulted in the figure as shown below. Decorate the control properties as per your prefer.

MSI2.jpg

I just wanted to write a few lines of code, so I bound the button's click event to show the text box's text:

MSI3.jpg

Primary Objective

So far so good. Now let's create an installer for the same Windows application. Right-click on the solution and add a new project to your solution like in the following figure:

MSI4.jpg

And add a Setup Project by "Other Project Types" -> "Setup and Deployment" -> "Visual Studio Installer" as in the following:

MSI5.jpg

The project will be added to the solution. Now open the file system editor by clicking on the project and select the option to open the file system editor, as shown in the following figure.
You'll get to see the Application Folder, User's Desktop and User's Program Menu.

MSI6.jpg

Right-click on the Application Folder and add an output project; the output project specifies the project we are creating an installer for, like in the following figure:

MSI7.jpg

Select "CreatingInstaller", in other words the Windows application project name in the "Add Output Project Group" window, select it as the primary output as shown below and click "Ok".

MSI8.jpg

The Primary output will be added as shown below, having a type defined as Output.

MSI9.jpg

In the meanwhile let's add some more functionality to our Windows application, let's read a file and show its output in a message box on button click. Therefore just add a text file, I called it Sample.txt to the "bin\debug\Input" folder, Input is the custom folder I created to place my txt file.

Write a few lines of code just to read the txt file from the Startup path, in my case "bin\debug". It could also be "bin\release" as per the project build, and specify the file folder name and file name to read the content. I chose to keep my txt file at the startup path so that I could explain how to create files and folders at the time of installation. Now we also need this Input folder and a Sample.txt file at the time of installation to be located at the location of the installed application.
For file operations I added the namespace System.IO, needless to specify this thou.

MSI10.jpg

Therefore running the application will show two message boxes, one after another showing the text box text and text from the Sample.txt file.

MSI11.jpg

MSI12.jpg


Now in this folder creation logic has to be implemented in the out setup project, so that when the application installs, it has all the pre-requisites required to run the application, like the Input folder and the Sample.txt file.

So, right-click on the Application Folder in the File system editor and add a folder. The folder will be created just below the Application Folder, name that folder Input.

MSI13.jpg

Right-click on the folder, select properties and mark Always Create property to True. That means the folder will always be created whenever we run the installer, after a fresh build release.

MSI14.jpg


Create Shortcuts

You can decorate your form to add an icon to it, that icon will also be required at the time of installation to create a shotcut icon to our application. Add an icon to the form like in the following figure:

MSI15.jpg

It is now time to add the Sample.txt file. Right-click the Input folder created and Add file to it, browse for the Sample.txt file in the Windows Application project we created earlier.

MSI16.jpg

To create a shortcut to the application, right-click on the Primary output in the middle window pane and select "Create Shortcut to Primary Output", name that shortcut as CreatingInstaller.

Select the properties of the shortcut by right-clicking it and add an icon to it. This icon will be created on the Desktop when the application launches. The following figures shows how to add an icon.

MSI17.jpg


MSI18.jpg


Cut the shortcut created at the Application Folder and paste it under the User's Desktop Folder. The job is done to create a shortcut to the user's Desktop.

MSI19.jpg

For shortcuts to be created in the User's Program Menu, add a new folder to the User's Program Menu that will be created at the program's menu location. In that folder create a new shortcut pointing to the primary output as done for creating a Desktop shortcut. The following three images shows the process:

MSI20.jpg

Name the folder CreatingInstaller.

Right-click on the middle window pane to create a new shortcut.

MSI21.jpg

Select the shortcut source to the primary output as selected.

Also add an icon to the shortcut, as done for the Desktop shortcut.

MSI22.jpg


Right-click the Application folder to set the properties of where to install the application, as in the following:

MSI23.jpg

Uninstall

We always have an option to uninstall the application from the Control panel's Programs and Features list (as simple as that) but how about creating our own uninstaller, that too is under the programs menu so that we do not need to disturb the Control Panel.

Step 1

Right-click on the File System on the target Machine and "Add Special Folder" -> "System Folder" as shown in the following figure:

MSI24.jpg


Step 2

Right-click on the newly created system folder and browse for the msiexec.exe file in the local System.Windows32 folder. This file provides the parameters and other data to install and uninstall the application based on certain parameters specified.

MSI25.jpg

Set the properties of the file exactly as shown in the following figure:

MSI26.jpg


Step 4

Now create a new shortcut under the User's program Menu and point its source to msiexec as shown below. You can add icons and a name to your shortcut. I have given it the name "Uninstall".

MSI27.jpg

Step 5

Press the F4 key by selecting the setup project. We see a list of properties, we can customize these properties as per our installation needs, like set Product name, Author, Installation location. I'll not go into a deep discussion about all this, since they are quite easy to understand and set.

Just take a note of the product code shown below in the list of properties. We will need the product code as a parameter to msiexec for uninstallation.

MSI28.jpg


Step 6

Right-click the Uninstall shortcut and set the arguments property as shown in following:
/x {product code} /qr
/x is for uninstalltion.
You can get the entire detailed list of parameters and their use at http://technet.microsoft.com/en-us/library/cc759262(v=ws.10).aspx, choose the one you prefer.

MSI29.jpg

Step 7

Save all and Rebuild the setup project.

Job Done !

Now our setup is ready to install our Windows application.

Just browse the debug folder location of the Setup project, we find a msi and a setup.exe, one can run either of the two to initiate the setup.

When started we see a setup wizard, having screens that welcomes User and that asks for the location to install to (already showing the default location).

MSI30.jpg


MSI31.jpg

MSI32.jpg

MSI33.jpg

After completing the wizard, click the Close button.

Now the job is done, we will see our shortcuts to the application created on the Desktop and the User's Program Menu like in the following figure.

MSI34.jpg

Now if we navigate to our installation location then we can also see the Input folder created and Sample.txt file inside it.

Run the application and see the output; it works perfectly as was when executed from Visual Studio.

MSI35.jpg

Click on uninstall to remove the application, the wizard launches as in the following:

MSI36.jpg

Custom Actions

I just want to provide a glimpse of Custom Actions we can define while creating a setup.

Custom actions are the actions that contains customized functionality apart from the default ones at the time of installation and uninstallation. For example my QC team reported a bug that when the application is run and in the background the application uninstall is done, the application continues to run. According to them it should show a message or close during uninstallation. It is difficult to explain them the reason, I opted for implementing their desire in the setup project.

1. Just add an installer class to the Windows application we created earlier. When we open the installer class we will see the events specified for each custom action, in other words for Installation, Uninstallation, Rollback,Commit.

MSI37.jpg


My need was to write code for uninstallation, so I wrote a few lines to satisfy the requirement.
The code contains the logic to find the running exe name at the time of uninstallation, if it matches my application exe name then just kill the process. I will not go into more details of that. I just want to explain the use of custom actions.


 

using System;

using System.Collections;

using System.Collections.Generic;

using System.ComponentModel;

using System.Configuration.Install;

using System.Diagnostics;

using System.Linq;

 

 

namespace CreatingInstaller

{

    [RunInstaller(true)]

    public partial class Installer1 : System.Configuration.Install.Installer

    {

        public override void Install(IDictionary savedState)

        {

            base.Install(savedState);

            //Add custom code here

        }

 

 

        public override void Rollback(IDictionary savedState)

        {

            base.Rollback(savedState);

            //Add custom code here

        }

 

        public override void Commit(IDictionary savedState)

        {

            base.Commit(savedState);

            //Add custom code here

        }

 

 

        public override void Uninstall(IDictionary savedState)

        {

            Process application = null;

            foreach (var process in Process.GetProcesses())

            {

                if (!process.ProcessName.ToLower().Contains("creatinginstaller")) continue;

                application = process;

                break;

            }

 

            if (application != null && application.Responding)

            {

                application.Kill();

                base.Uninstall(savedState);

            }

        }

 

    }

}

2. Click on the Custom Actions Editor after selecting CreatingInstallerSetup project.

MSI38.jpg

3. We see the Custom Actions Editor pane in the left window, right-click it to add a custom action and select the primary output in the Application Folder.

MSI39.jpg

MSI40.jpg


4. We see the primary output added as custom actions now. Now at the time of uninstallation my custom action will be fired, and the application will be closed while uninstalling it.

MSI41.jpg

.Net Framework

What if the installation machine does not have a .Net Framework? We can specify our own package supplied with the installation, so that our application does not depend on the .Net Framework of the client machine, but points to the package we supplied to it to run.

Right-click on the Setup project, to open the properties window.

Here we can specify pre-requisites for the application to install. Just click on the Prerequisites button and, in the prerequisites window, select the checkbox for the .Net Framework that the application needs, and select the radio button at nunber 2, in other words Download the prerequisites from the same location as my application. Press "OK" to save the project and re-build it.

MSI42.jpg



Now when we browse to the Debug folder of the Setup project we see two more folders as a result of the actions we just did.

Now this entire package has to be supplied to the client machine for the installation of the application.

MSI43.jpg


Now re-install the application from setup.exe, and launch it using shortcuts.

Conclusion

This tutorial covers the basic steps for creating the installation project. I did not go very deep into explaining the registry and license agreements though. There are many things to be explored yet to understand and master this topic. However, this article was just a start for a developer to play around with setups and deployments. Happy Coding.