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


Downloads

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • With JRebel, developers get to see their code changes immediately, fine-tune their code with incremental changes, debug, explore and deploy their code with ease (both locally and remotely), and ultimately spend more time coding instead of waiting for the dreaded application redeploy to finish. Every time a developer tests a code change it takes minutes to build and deploy the application. JRebel keeps the app server running at all times, so testing is instantaneous and interactive.

  • Live Event Date: April 22, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Database professionals — whether developers or DBAs — can often save valuable time by learning to get the most from their new or existing productivity tools. Whether you're responsible for managing database projects, performing database health checks and reporting, analyzing code, or measuring software engineering metrics, it's likely you're not taking advantage of some of the lesser-known features of Toad from Dell. Attend this live …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds