Compare MSIs using C#


While cleaning up some old files I found a project that compares file manifests between MSIs. At the time we needed the ability to quickly determine if the files contained in a set of new MSIs contained at least the same set of files that was generated using a previous build process. While there are other tools that can compare MSIs, this code is lightweight and command-line scriptable.


References


C# Code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.Deployment.WindowsInstaller;
using Microsoft.Deployment.WindowsInstaller.Package;

namespace MsiCompareTool{
    class Program{
        static void Main(string[] args){
            List<String> Msi1Files = new List<string>();
            List<String> Msi1Files2 = new List<string>();
            using (var package = new InstallPackage(args[0], DatabaseOpenMode.ReadOnly)){
                foreach (var filePath in package.Files){
                    //Console.WriteLine(filePath.Key);
                    Console.WriteLine(filePath.Value.ToString());
                    Msi1Files.Add(filePath.Value.ToString());
                }

                //Console.WriteLine("Finished MSI1");
                //Console.WriteLine("-----");           
            }

            using (var package = new InstallPackage(args[1], DatabaseOpenMode.ReadOnly)){
                foreach (var filePath in package.Files){
                    //Console.WriteLine(filePath.Key);
                    Console.WriteLine(filePath.Value.ToString());
                    Msi1Files2.Add(filePath.Value.ToString());
                }
                //Console.WriteLine("Finished MSI2");
            }

            // Compare!
            foreach (var file in Msi1Files){
                if (!Msi1Files2.Contains(file)){
                    Console.WriteLine(String.Concat("File '", file, "' is expected but not present in MSI 2"));
                }
            }

            //uncomment this if you want the tool to wait for a keypress after displaying missing files
            //Console.Read();
        }
    }
}


When compiled this tool accepts 2 input arguments:

  • Arg 1: Original or Reference MSI
  • Arg 2: New MSI you want to check

The idea is that you are checking to see if the 'new' MSI is missing any files present in the 'old' one. For the use case that I was targeting, it did not matter if there were EXTRA files in the new MSI- it was just important that we were not missing any of the files present in the previous version.

This tool could be expanded to check if the files are the same (hash) and potentially do other checks- I just never had cause to any further than this simple check. If you need more insight into your MSIs, you could use a tool like SuperOrca.