Custom User Interface for MSI Packages Using C# .NET



Custom user interface for MSI packages using C# .Net


Nvn Installer ships MsiDotNet API (NvnInstaller.MsiDotNet.dll) which is developed using .Net framework 2.0. So installation package author can use this API to create good looking installer UI using .Net framework, WPF and 3rd party libraries. This API is very useful when some other tasks need to be completed other than installation.

For example:
  • license key validation using a web service
  • installing your software only when payment is done
  • displaying advertisements
  • Installing multiple software
  • accepting inputs from user and updating remote database
  • any crazy things that you can accomplish using .Net

MsiInstaller Class

MsiInstaller is the basic class which initiates, controls, terminates installation process. Following are the useful functions which .Net application can use.
Install() - All features and components are installed. Install(List listOfFeatures) - Only the list of features which are supplied as argument are installed.
Remove() - All features and components are uninstalled. Remove(List listOfFeatures) - Only the list of features which are supplied as argument are uninstalled.
Repair() - MsiInstaller class detects list of features already installed on local system and re-installs them.
Update(List installList, List uninstallList) Install List - Feature is reinstalled if it is already installed or that feature is freshly installed. Uninstall List - Feature which are already installed are removed or other features are ignored.
.Net application needs to subscribe InstallerMessageReceived event to handle Windows Installer messages. InstallerMessage object can be typecasted to specific InstallerMessage classes to obtain detailed information

For Example Collapse
   void msiInstaller_InstallerMessageReceived(object sender, InstallerMessageEventArgs e) {
if (e.InstallerMessage.Type == InstallerMessageType.ProgressReport) {
if (reset) {
ProgressReportMessage progressReportMessage = (ProgressReportMessage)e.InstallerMessage;
if (approximate && installPrograssBar.Maximum < (installPrograssBar.Value + progressReportMessage.TicksMoved)) return;
installPrograssBar.Value += (int)progressReportMessage.TicksMoved;
} else if (e.InstallerMessage.Type == InstallerMessageType.ResetMessage) {
reset = false;
// set progress bar properties
ResetMessage resetMessage = (ResetMessage)e.InstallerMessage;
installPrograssBar.Maximum = (int)resetMessage.Ticks;
installPrograssBar.Minimum = 0;
installPrograssBar.Step = 1;
installPrograssBar.Value = 0;

approximate = resetMessage.IsApproximate;
reset = true;
} else if (e.InstallerMessage.Type == InstallerMessageType.ActionData) {
} else if (e.InstallerMessage.Type == InstallerMessageType.ActionStart) {
ActionStartMessage actionStartMessage = (ActionStartMessage)e.InstallerMessage;
SetLabel(actionStartMessage.Action + ": " + actionStartMessage.Description);
} else if (e.InstallerMessage.Type == InstallerMessageType.FileInUse) {
MsiResponse userAction = (MsiResponse)MessageBox.Show("file in use:" + ((FileInUseMessage)e.InstallerMessage).FilePath, "File in use", MessageBoxButtons.AbortRetryIgnore);
} else if (e.InstallerMessage.Type == InstallerMessageType.InstallationComplete) {
SetLabel("Installation Completed");

// Cancel installation
if (cancel && e.SetUserAction) {

About features

MsiFeature is the basic class which contains all information about a feature. Installer user interface author can use the list of features to selectively install/uninstall. Use MsiInstaller.FeatureTree to get list of feature. This property gives only root features. Use ChildFeatures property recursively to get complete list of features.
For example

    public void LoadFeatures() {
MsiInterface msiInterface = new MsiInterface();
List features = msiInterface.FeatureTree;
foreach (MsiFeature feature in features) {
LoadFeatureTree(feature, null);

private void LoadFeatureTree(MsiFeature feature, TreeNode node) {
TreeNode newNode = null;
if (node == null) {
newNode = tvFeatures.Nodes.Add(feature.Title);
} else {
newNode = node.Nodes.Add(feature.Title);

newNode.Checked = feature.IsAlreadyInstalled;

if (feature.ChildFeatures != null) {
foreach (MsiFeature childFeature in feature.ChildFeatures) {
LoadFeatureTree(childFeature, newNode);

Use IsAlreadyInstalled property of MsiFeature to know whether feature is already installed on local system.

Configuring with Nvn Installer

  • Create MSI package using Nvn Installer and save project file.
  • Create windows application using NvnInstaller.MsiDotNet and MSI package created using Nvn Installer. Name of application should same as name of MSI file. For example Test.exe for Test.msi
  • Setting parameters in Custom UI Application tab
    1. Open the project which is used for creating installation package.
    2. Open Custom UI Application tab
    3. Browse and select folder containing custom UI application and its supporting files
    4. Above action list all file in supporting files list. Now select only those file which you like to package.
  • Click Build >> Build MSI file or Press F6

This article was originally published on August 25th, 2010


Most Popular Programming Stories

More for Developers

RSS Feeds
