Windows Installer MSI Reference

This page is a reference for creation of simple .msi installation files as are they used during deployment cycles at bitnova. For this purpose, the existence of the Microsoft Windows SDK is necessary. The current version downloadable from Microsoft site at the time of this writing was v7.0. After the installation of Windows SDK, it is also necessary to install the Orca editor, usually found inside the installation of the SDK.

Usefull Resources:
 * Orca editor setup - C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\Orca.msi
 * GUID generation utility - C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\GUIDGen.exe
 * MSI sample file: Schema.msi - C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\msitools\Schemas\MSI\Schema.msi
 * MSI UI sample file: UISample.msi - C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\msitools\Templates\MSI\UISample.msi

MSI Reference example will work an an imaginary deployment folder C:\Deployment, containing one file only: Sample.txt, with a single line of text: "This is a sample file for msisample install.", size: 44 bytes.

Preparation

 * 1) Open Orca Editor. From the View menu, open Summary Information and enter valid information in boxes:




 * Package Code - needs to be unique and can be generated by using New GUID button
 * Schema represents the version of the installer for which the msi package is created. Minimum value should be 200, but currently 400 is recommended
 * Do not check UAC compliant as it will force the setup not to request administrative privileges and will instead require the user to log in as an administrator.


 * 1) Add necessary tables. The .msi file is a relational database. The following tables need to be added to the package in order to make a simple setup:


 * Error and _Validation tables - always required;
 * Property table - required for specifying product information;
 * InstallExecuteSequence - required if you want any of the setup actions to actually happen;
 * Directory - for describing the directory structure;
 * Media - describing cab files, disks, deployment packages if necessary. It is always required in order to establish a sequence of files stored on media;
 * Feature, Component and FeatureComponents tables - will describe in a relational fashion the components contained in the installation kit;
 * File table - actual file references.


 * 1) Copy default values from Schema.msi and UISample.msi.

Some tables are already filled in with default data. This is the case for Error, _Validation and InstallExecuteSequence, which can be copied from the UISample.msi file. For this, open the sample file with Orca, go to table, select desired rows with Click and Shift+Click then copy them with Ctrl+Shift+C. Go back to your .msi file, select table then right click and Paste Rows.


 * Note: For the _Validation table, do not copy all the records (it will fail at some point), but instead copy the records for each table you have in your msi database at a time.


 * 1) Define properties for your product in the Property table. These properties are added in pairs of NAME|VALUE. At least, you have to define the following:


 * ProductName
 * Manufacturer
 * ProductLanguage - just put 0
 * ProductVersion - can be anything
 * ProductCode - it must be a GUID in {}. Use the GUIDGen utility mentioned at the beginning


 * 1) Add Media Record. In the Media table, Add a row with following values:


 * DiskId = 1
 * LastSequence = 1

Component Definition

 * 1) Define directory structure in the Directory table.

The entries in the Directory table have the form (Directory|Directory_Parent|DefaultName). There is one record required to be introduced, TARGETDIR which defines the root path where the files will be copied. The usual way is to enter the (TARGETDIR| |SourceDir) record which says that the target directory should be logically mapped to the current directory (SourceDir) from which the installation takes place.

From here, any directory structure can be defined by declaring each node in a hierarchical manner and specifying the mapping involved, following the format (LOGICALNAME|PARENTNODE|[targetname]:[sourcename]). The simplest example, for this tutorial would be (SAMPLEDIR|TARGETDIR|.) which states that the logical node SAMPLEDIR, will have the path starting with the parent folder (TARGETDIR) and localized at the same physical level (.) both in source and destination.

Other possible combinations could be (SAMPLEDIR|TARGETDIR|sample) which would map to the sample subdirectory both in target and source folders, or (SAMPLEDIR|TARGETDIR|.:sample) which says that physically, SourceDir/sample folder maps to TARGETDIR/. folder.


 * 1) Define a feature

Declare a feature in the Feature table by inserting the following record:


 * Feature = Sample
 * Feature Parent = nothing
 * Title = Sample
 * Description = Sample Text File
 * Display = 1
 * Level = 1
 * Directory_ = SAMPLEDIR (this will link to the node in Directory table)
 * Attributes = 0


 * 1) Define a Component


 * Component = Sample
 * ComponentId = use the GUIDGen utility to generate a GUID and copy it to clipboard then paste it here
 * Directory_ = SAMPLEDIR (looks like this is somewhat redundant, as there is already a Directory reference in the Feature table)
 * Attributes = 2 (means that the resource is available locally and also from source)
 * Condition = nothing (this will be usefull for conditional install on more complex cases)
 * KeyPath = Sample.txt - Key path reffers actually to the primary file targeted by the component, which is usefull when adding shortcuts by referencing through features, which is not covered in this tutorial.


 * 1) Map Feature to Component

In FeatureComponents add the record (Sample|Sample)


 * 1) Declare the files to be copied in File table


 * File = Sample.txt (this is actually an ID not the name of the file itself)
 * Component_ = Sample
 * FileName = Sample.txt
 * FileSize = 44
 * Version = nothing
 * Language = nothing
 * Attributes = 0
 * Sequence = 1 (this must not cross the LastSequence value from the Media table)

Adding Programs Menu Shortcuts
You can add program menu shortcuts or desktop shortcuts, the procedure is identical.


 * 1) Add the Shortcut table if it not added already to the msi package and copy the validation records from a .msi sample file, such as Schema.msi;


 * 1) Define directory structure. For this, one should add entries that map themselved to a predefined path, such as ProgramMenuFolder. The following entries provide a good example for how shortcuts on bitnova products are added:


 * (ProgramMenuFolder|TARGETDIR|.) - this will map logically the ProgramMenuFolder to the same location as installation target. That's only a logical mapping, not physical; the ProgramMenuFolder will keep its default value, but child nodes will mapped accordingly on folders and files from the installation media;
 * (BITNOVAMENU|ProgramMenuFolder|bitnova:.) - it says that a node should be created that will map ProgramMenuFolder/bitnova to the installation folder;
 * (SAMPLEMENU|BITNOVAMENU|Sample:.) - again, the mapping goes to ProgramMenuFolder/bitnova/Sample = SourceDir;


 * 1) Define the shortcut itself, although it is recommended that a new feature and component to be added for this. But this step is straightforward, as one can declare directly a shortcut by simply adding a record in the Shortcut table:


 * Shortcut = name of the shortcut (this is an ID);
 * Directory = SAMPLEMENU
 * Name = Sample.txt - actual name of the shortcut that will appear in the Progams Menu
 * Component = Sample - Also note that it is recommended to use a different feature and component for shortcut installation
 * Target = [#Sample.txt] - link to the actual file
 * Arguments = nothing if you don't have anything to pass along as an argument to an executable
 * Description = nice description of the shortuct
 * rest of the fields can be left empty for this case

Adding url shortcuts
Adding url shortcuts is useful when access to online resources is desired. A simple method for this would be to use the IniFile table.


 * 1) The first step is to add the IniFile table to the .msi installation file and then copy the validation records from a sample .msi database such as Schema.msi


 * 1) A simple entry for an url pointing to bitnova wiki would look like:


 * IniFile = url_wiki - this is an ID;
 * FileName = url_wiki.url - represents the actual filename of the link wich will be added in the shortcut folder. Also, for long filenames, the short filename must be added as well like INSTAL~1.URL|InstallSite.url. Normally, this field would be set to an actual .ini file name and because .url files are similar in structure with .ini files, this is why you can add url shortcuts in this table;
 * DirProperty = SAMPLEMENU - the shortcut dir
 * Section = InternetShortcut - Section, Key and Value define the properties of a normal .ini entry, only that it is not stored in an ini file;
 * Key = URL
 * Value = http://www.bitnova.ro/wiki;
 * Action = 0;
 * Component = Sample, or SampleMenu if we reffer to the conditional setup of shortcuts.

Testing

 * 1) Test your installation file

To test the installation, create a batch file next to your msi file, then enter the following command inside:

msiexec /i file.msi TARGET="C:\Program Files\Sample" /L*v log.txt