Custom User Interface for MSI Packages Using C# .NET

Custom user interface for MSI packages using C# .Net

Introduction

Windows installer has its own way to display installer user interface which is far different from other technologies. MSI supports few controls compared to .Net or other platform. Though it is not very difficult, still it is hard job to develop sophisticated installation package with good user interface, even after using well known installer software..

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) {
SetLabel(((ActionDataMessage)e.InstallerMessage).Message);
} 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);
msiInstaller.SetUserAction(userAction);
} else if (e.InstallerMessage.Type == InstallerMessageType.InstallationComplete) {
SetLabel("Installation Completed");
}

// Cancel installation
if (cancel && e.SetUserAction) {
msiInstaller.SetUserAction(MsiResponse.Cancel);
}
}

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
Collapse

    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

More by Author

Get the Free Newsletter!

Subscribe to Developer Insider for top news, trends & analysis

Must Read