I have recently been creating a new UI Module for IIS 7 and as part of this I wanted to install my module automatically using a MSI file. With the help of CarlosAg from the IIS product team I have made my UI module work really well and also managed to create a setup for it.
The setup installs the files into the GAC, and does the registration and de-registration in the IIS administration.config file during install/uninstall.
For details on how to do this please go to http://blogs.msdn.com/carlosag/archive/2008/11/10/CreatingSetupProjectForIISusingVisualStudio2008.aspx
So it was all working fine but when I deployed it to a 64Bit machine I got the following error during the install.
Now I was lost but Carlos did some digging and found an article that explained what happened which you can read by clicking the link below.
Basically the problem is (quoted from heath's blog)
When you build the Windows Installer project in Visual Studio it embeds the 32-bit version of InstallUtilLib.dll into the Binary table as InstallUtil. When Windows Installer executes your managed custom action it actually is calling the
ManagedInstall entry point function from InstallUtilLib.dll as a type 1 deferred custom action (1025) which creates an instance of the CCW
System.Configuration.Install.IManagedInstaller interface and runs your
Installer classes. Since the native InstallUtilLib.dll is 32-bit it loads the 32-bit Framework which will throw the
BadImageFormatException since your managed class library is 64-bit.
So his blog goes on with a method you can use to update the DLLs binary data in the MSI file using a tool called ORCA which can be downloaded from http://www.technipages.com/download-orca-msi-editor.html
I wanted a more automated solution so I wrote the following code which uses the Windows Installer COM Object to open the database and replace the binary file.
<?xml version="1.0" encoding="utf-8" ?>
<add key="InstallUtil64BitFileSpec" value="\\ccrowe-test\c$\Windows\Microsoft.NET\Framework64\v2.0.50727\InstallUtilLib.dll"/>
<add key="MSIFileSpec" value="C:\dev\Projects\IIS7\Extensibility\FTPADUserEditor\SetupFTPADUserEditor\Debug\SetupFTPADUserEditor.msi"/>
My C# Source
// You must add a reference to the COM Object "Microsoft Windows Installer Object Library 1.0"
// which is located in c:\windows\system32\msi.dll
// You must also add a reference to System.Configuration
// For more details of why this code was written see the following site
static void Main(string args)
bool ChangesMade = false;
Console.WriteLine("Update an MSI File with a 64bit version of InstallUtilLib");
string InstallUtil64BitFileSpec = ConfigurationManager.AppSettings["InstallUtil64BitFileSpec"];
string MSIFileSpec = ConfigurationManager.AppSettings["MSIFileSpec"];
if (System.IO.File.Exists(InstallUtil64BitFileSpec) == false)
Console.WriteLine("File Not Found : " + InstallUtil64BitFileSpec);
if (System.IO.File.Exists(MSIFileSpec) == false)
Console.WriteLine("File Not Found : " + MSIFileSpec);
Console.WriteLine("MSIFile:" + Environment.NewLine + MSIFileSpec);
Console.WriteLine("InstallUtil: " + Environment.NewLine + InstallUtil64BitFileSpec);
Console.WriteLine("Opening the MSI File");
WindowsInstaller.Installer i = (WindowsInstaller.Installer)new Fix64BitMSIFile.Installer();
WindowsInstaller.Database db = i.OpenDatabase(MSIFileSpec, WindowsInstaller.MsiOpenDatabaseMode.msiOpenDatabaseModeTransact);
Console.WriteLine("Running SQL Query for InstallUtil in the Binary MSI table");
// NOTE: The ` is correct in the SQL statement below - it is not " or '
WindowsInstaller.View v = db.OpenView("SELECT `Name`,`Data` FROM `Binary` where `Binary`.`Name` = 'InstallUtil'");
WindowsInstaller.Record Record = v.Fetch();
if (Record != null)
Console.WriteLine("Updating the Binary Data for InstallUtil");
ChangesMade = true;
Console.WriteLine("Error : InstallUtil not found in the Binary MSI Table");
Console.WriteLine("Commiting the changes to the database");
Hopefully this may help someone else in the future.
In the mean time it is back to the development of my IIS 7 Module....