Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to extract data (file count) from MSI "File" Table

In our build process there is currently the potential for non-code based files (such as image files) to be added to our web project, but not included in the MSI installer built by WiX.

To help prevent this, I want to perform the following in the AfterBuild target for our WiX project:

  • Get a count of all files built (output from web deployment project)
  • Get a count of all files built into MSI (from "File" table in MSI)
  • Compare counts and fail build if they don't match

If I fire up Orca I can easily see the File table and count, but I don't know how to automate this from MSBuild. Is there some API or other mechanism to get this information out of an MSI?

I don't mind writing a custom MSBuild task to extract the MSI File table count.

like image 495
si618 Avatar asked Mar 20 '09 21:03

si618


People also ask

How do I extract MSI files?

Extract an MSI File using the Command Line Windows has the ability to allow the MSI file contents to be extracted using the Command Prompt or via a script. Simply open the Run box (Win+R) or a Command Prompt and type msiexec to get a list of arguments.

How do I view MSI contents?

View MSI files by launching the app, or by right-clicking an MSI file in File Explorer and choosing "Open in MSI Viewer".

How do I extract MSI files in Windows 10?

Just download Universal Extractor. It extracts all types of files, including .exe,. msi,. rar,.

What is Lessmsi?

lessmsi is a portable app with a GUI or command-line to view and extract an MSI file's contents. MSI stands for Microsoft Installer, and it works just like an executable does. Double-click any MSI, and the install routine will begin.


2 Answers

Create a new visual studio project, add a reference to c:\windows\system32\msi.dll and use the following code to read the number of files in a msi file:

Type installerType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
var installer =
   (WindowsInstaller.Installer)Activator.CreateInstance(installerType);
var msi = installer.OpenDatabase(@"path\to\some\file.msi", 0);
var fileView = msi.OpenView("SELECT FileName FROM File");
fileView.Execute(null);
int fileCount = 0;
while (fileView.Fetch() != null)
{
   fileCount++;
}
Console.WriteLine(fileCount);

This code uses the WindowsInstaller.Installer COM object, which is the entry-point for the windows installer automation API. Take a look at the complete reference documentation.

edit: apparently wix comes with managed assemblies (in C:\program files\Windows Installer XML v3\sdk) which wrap msi.dll. I guess this is what Rob is referring to by "DTF" in his answer. Using the types in the Microsoft.Deployment.WindowsInstaller assembly and namespace would simplify the code sample to this:

var database = new Database(@"\path\to\some\file.msi");
var list = database.ExecuteQuery("SELECT FileName FROM File");
Console.WriteLine(list.Count);
like image 99
Wim Coenen Avatar answered Nov 02 '22 01:11

Wim Coenen


MSI files are little baby databases with a custom SQL engine. You just need to run the query:

SELECT `File` FROM `File` 

and count the number of rows that come back. Easiest way to integrate into an MSBuild Task would probably be to use WiX's DTF which provides managed wrappers for all of the MSI APIs.

The solution will be really simple once you get all the tools in place.

like image 32
Rob Mensching Avatar answered Nov 02 '22 03:11

Rob Mensching