posts - 0, comments - 1573, trackbacks - 0

64-bit Managed Custom DLL Actions with Visual Studio do not work properly

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.

64BitIIS7InstallError

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.

http://blogs.msdn.com/heaths/archive/2006/02/01/64-bit-managed-custom-actions-with-visual-studio.aspx

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.

 

My App.Config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
      <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"/>
  </appSettings>
</configuration>

 

My C# Source

using System;
using System.Configuration;

// 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
// http://blogs.msdn.com/heaths/archive/2006/02/01/64-bit-managed-custom-actions-with-visual-studio.aspx
namespace Fix64BitMSIFile
{
    class Program
    {
        static void Main(string[] args)
        {
            bool ChangesMade = false;

            Console.WriteLine("Update an MSI File with a 64bit version of InstallUtilLib");
            Console.WriteLine();

            string InstallUtil64BitFileSpec = ConfigurationManager.AppSettings["InstallUtil64BitFileSpec"];
            string MSIFileSpec = ConfigurationManager.AppSettings["MSIFileSpec"];

            if (System.IO.File.Exists(InstallUtil64BitFileSpec) == false)
            {
                Console.WriteLine("File Not Found : " + InstallUtil64BitFileSpec);
                return;
            }
            if (System.IO.File.Exists(MSIFileSpec) == false)
            {
                Console.WriteLine("File Not Found : " + MSIFileSpec);
                return;
            }

            Console.WriteLine("MSIFile:" + Environment.NewLine + MSIFileSpec);
            Console.WriteLine();
            Console.WriteLine("InstallUtil: " + Environment.NewLine + InstallUtil64BitFileSpec);
            Console.WriteLine();
            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'");
            v.Execute(null);
            WindowsInstaller.Record Record = v.Fetch();
            if (Record != null)
            {
                Console.WriteLine("Updating the Binary Data for InstallUtil");
                Record.SetStream(2, InstallUtil64BitFileSpec);
                v.Modify(WindowsInstaller.MsiViewModify.msiViewModifyUpdate, Record);
                ChangesMade = true;
            }
            else
            {
                Console.WriteLine("Error : InstallUtil not found in the Binary MSI Table");
            }
            v.Close();
            if (ChangesMade)
            {
                Console.WriteLine("Commiting the changes to the database");
                db.Commit();
            }

            Console.WriteLine();
            Console.WriteLine("Completed.....");
        }
    }
}

 

Hopefully this may help someone else in the future.

In the mean time it is back to the development of my IIS 7 Module....

Print | posted on Thursday, November 13, 2008 9:52 AM |

Feedback

Gravatar

# re: 64-bit Managed Custom DLL Actions with Visual Studio do not work properly

I'm sorry, for the life of me I can't figure out how to get this line to work:

WindowsInstaller.Installer i = (WindowsInstaller.Installer)new Fix64BitMSIFile.Installer();

Can you tell me what I'm missing here? thanks in advance, this little snipit of code is gonna be a HUGE help!
3/10/2009 5:56 PM | Serpent77
Gravatar

# re: 64-bit Managed Custom DLL Actions with Visual Studio do not work properly

Nice one! I had suspected this was the problem, thanks for the great information.

Adam
5/20/2009 10:08 PM | Adam Toth
Gravatar

# website hosting

IIS 7.0 is one of the products that my team is shipping later this year that I'm most excited about. It is the most significant release of our web-server that we've done since IIS 1.0, and introduces a huge number of improvements for both administrators and developers.
7/9/2009 1:09 AM | website hosting
Gravatar

# re: 64-bit Managed Custom DLL Actions with Visual Studio do not work properly


// replace this
WindowsInstaller.Installer i = (WindowsInstaller.Installer)new ix64BitMSIFile.Installer();

// with this
Type classType = Type.GetTypeFromProgID("WindowsInstaller.Installer");
Object installerClassObject = Activator.CreateInstance(classType);
WindowsInstaller.Installer i = (WindowsInstaller.Installer)installerClassObject;
7/18/2009 12:15 AM | Pin0

Post Comment

Title  
Name  
Email
Url
Comment   
Please add 4 and 3 and type the answer here:

Powered by:
Powered By Subtext Powered By ASP.NET