Getting Started with the Windows Installer SDK Environment

Written by

in

How to Build MSI Packages Using Windows Installer SDK Windows Installer (MSI) remains the gold standard for enterprise software deployment. While modern frameworks like Wix Toolset or Advanced Installer wrap this technology in friendlier interfaces, building a package directly with the Windows Installer SDK provides an unmatched understanding of how MSI works under the hood.

This guide walks you through building a basic MSI package from scratch using the native tools provided in the Windows Installer SDK. 1. Prerequisites and Environment Setup

Before writing any code, you need to gather the necessary tools from Microsoft.

Install the Windows SDK: Download the latest Windows SDK via the Visual Studio Installer or directly from Microsoft.

Locate the Tools: Navigate to your SDK installation directory (typically C:\Program Files (x86)\Windows Kits\10\bin<version>\x64).

Essential Executables: Ensure you have access to Orca.exe (database viewer), MsiMsp.exe, and the VBScript automation scripts (WiBuild.vbs, WiGuid.vbs) located in the SDK’s Samples directory. 2. Understanding the MSI Database Structure

An MSI file is not a compiled binary; it is a relational database containing dozens of interconnected tables. To build an MSI from scratch, you must populate the core tables that dictate installation behavior:

ProductInfo Tables: Property, ProductCode, and UpgradeCode define what the software is and how it manages versions.

Layout Tables: Directory, Component, and File define where the files live on the disk and how they map to the target system.

Behavior Tables: InstallExecuteSequence and InstallUISequence dictate the exact execution order of the installation steps. 3. Creating the Database Schema

To build the package, you will use a blank database template (schema.msi) provided in the SDK or write a script to generate a new database using the Windows Installer Automation Interface. Step 1: Generate Unique GUIDs

Every MSI requires a unique ProductCode and ComponentId. Use the SDK script WiGuid.vbs or PowerShell to generate these: powershell [guid]::NewGuid().ToString().ToUpper() Use code with caution. Step 2: Write the SQL Installation Script

You can interact with the MSI database using SQL queries via Windows Installer Windows Scripting Host (WSH) interfaces. Create a script named BuildPackage.vbs to build your database layout:

Dim installer, database, view ‘ Create Installer object and open a blank database Set installer = CreateObject(“WindowsInstaller.Installer”) Set database = installer.OpenDatabase(“MyApplication.msi”, 1) ’ 1 = Create/Overwrite ‘ Insert Properties ExecuteSQL database, “INSERT INTO Property (Property, Value) VALUES (‘ProductName’, ‘My Application’)” ExecuteSQL database, “INSERT INTO Property (Property, Value) VALUES (‘ProductVersion’, ‘1.0.0’)” ExecuteSQL database, “INSERT INTO Property (Property, Value) VALUES (‘Manufacturer’, ‘My Company’)” ExecuteSQL database, “INSERT INTO Property (Property, Value) VALUES (‘ProductCode’, ‘{YOUR-GUID-HERE}’)” ExecuteSQL database, “INSERT INTO Property (Property, Value) VALUES (‘UpgradeCode’, ‘{YOUR-SECOND-GUID-HERE}’)” ‘ Commit changes database.Commit Sub ExecuteSQL(db, sqlQuery) Set view = db.OpenView(sqlQuery) view.Execute view.Close End Sub Use code with caution. 4. Defining Directories and Component Mapping

An MSI requires a strict directory structure. You must map your source files to target destination folders using the Directory table.

Add the following queries to your build script to establish the ProgramFilesFolder as the target installation path:

’ Define Directory Structure ExecuteSQL database, “INSERT INTO Directory (Directory, Directory_Parent, DefaultDir) VALUES (‘TARGETDIR’, “, ‘SourceDir’)” ExecuteSQL database, “INSERT INTO Directory (Directory, Directory_Parent, DefaultDir) VALUES (‘ProgramFilesFolder’, ‘TARGETDIR’, ‘.’)” ExecuteSQL database, “INSERT INTO Directory (Directory, Directory_Parent, DefaultDir) VALUES (‘INSTALLDIR’, ‘ProgramFilesFolder’, ‘MyApplication’)” ‘ Define Component ExecuteSQL database, “INSERT INTO Component (Component, ComponentId, Directory_, Attributes, Condition, KeyPath) VALUES (‘MainExecutable’, ‘{COMP-GUID-HERE}’, ‘INSTALLDIR’, 0, “, ‘myapp.exe’)” ‘ Define File Table Link ExecuteSQL database, “INSERT INTO File (File, Component_, FileName, FileSize, Version, Language, Attributes, Sequence) VALUES (‘myapp.exe’, ‘MainExecutable’, ‘myapp.exe’, 102400, ‘1.0.0.0’, ‘1033’, 512, 1)” Use code with caution. 5. Adding the Standard Sequence and Validating

Without an execution sequence, Windows Installer will open the MSI but execute nothing. You must populate the InstallExecuteSequence table with standard actions like LaunchConditions, CostInitialize, InstallFiles, and WriteRegistryValues.

ExecuteSQL database, “INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (‘LaunchConditions’, “, 100)” ExecuteSQL database, “INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (‘CostInitialize’, “, 800)” ExecuteSQL database, “INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (‘FileCost’, “, 900)” ExecuteSQL database, “INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (‘CostFinalize’, “, 1000)” ExecuteSQL database, “INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (‘InstallValidate’, “, 1400)” ExecuteSQL database, “INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (‘InstallFiles’, “, 4000)” ExecuteSQL database, “INSERT INTO InstallExecuteSequence (Action, Condition, Sequence) VALUES (‘InstallFinalize’, “, 6600)” Use code with caution. Compiling and Validating Run your script to generate MyApplication.msi.

Open the resulting file using Orca.exe from the SDK to visually inspect that all tables populated correctly.

Validate the package using Evalcom2.exe (Internal Consistency Evaluator) or Orca’s built-in validation to ensure there are no ICE database errors.

Building an MSI package directly via the Windows Installer SDK demands precision, careful GUID management, and a firm grasp of relational SQL syntax. While modern development pipelines usually abstract these steps away, mastering this low-level approach gives you the ultimate control to debug, reverse-engineer, and optimize complex deployment packages for corporate infrastructure. To tailor this guide further, let me know:

Comments

Leave a Reply

Your email address will not be published. Required fields are marked *