How I found out that mixed mode is cool

We ship a DDEX provider with Connector/Net.  This provider plugs into Visual Studio and integrates into server explorer allowing a user to create data connections to MySQL from within the IDE.  This integration is handled, in large part, by a lengthy series of registry entries.  Until 5.2.2, these entries were made by my installer which is written in WiX.  Having the registry changes made in the installer has two problems.  First, I often need to register the provider during debugging and I don't want to do a full install of the product so I end up hand editing a registry file and manually merging that file.  This a awkward at best.  Second I plan to ship a stand-alone configuration utility in 5.3 that will allow the user to configure which installed version of Connector/Net should be used for VS integration. Currently you can only have one instance installed at a time.

My approach to solving this was to write an installer class that made the registry changes for me and just use installutil to register the assembly.  I was already doing this with my core and web assemblies so this is nothing new.  The problem is that installutil will scan the assembly and all referenced assemblies for types looking for installer classes.  This fails when some of the Microsoft assemblies are scanned.  After much effort I gave up and decided to write my own installutil that I would ship with my installer. 

I had no trouble creating this application and then set about executing it from within my installer.  I attempted to use the CAQuietExec custom action available with WiX v3 but just couldn't make it work right.  So I gave up and decided to write my own execute custom action.

So I cracked open Visual Studio 2008 and read a couple of blogs about custom action writing.  One of them mentioned mixing managed and unmanaged code, the unmanaged code being necessary for the proper DLL exports.  I decided I had to see this work.

Within minutes I had a DLL project setup with the /clr option and had hacked out the following code:

   1: extern "C" __declspec(dllexport) UINT InstallAssembly(MSIHANDLE hMSI)
   2: {
   3:     System::Windows::Forms::MessageBox::Show("boo");
   4:     TCHAR name[261]={0};
   5:     DWORD len=261;
   6:  
   7:     UINT result = ::MsiGetProperty(hMSI, TEXT("CustomActionData"), name, &len);
   8:     InstallVSAssembly(name, true);
   9:     return ERROR_SUCCESS;
  10: }
  11:  
  12: bool InstallVSAssembly(char *assemblyName)
  13: {
  14:     String^ str = gcnew String(assemblyName);
  15:     bool uninstalling = false;
  16:     IDictionary mySavedState = new Hashtable();
  17:     int arg = 0;
  18:  
  19:     InstallContext context = new InstallContext();
  20:     while (arg < args.Length)
  21:     {
  22:         string[] parts = args[arg++].Split('=');
  23:         context.Parameters.Add(parts[0], parts[1]);
  24:     }
  25:  
  26:     Installer installer = null;
  27:     try
  28:     {
  29:         Assembly assem = Assembly.LoadFrom(file);
  30:         installer = (Installer)assem.CreateInstance("MySql.Data.VisualStudio.MyInstaller");
  31:         if (installer == null)
  32:         {
  33:             Console.WriteLine("Unable to find an installer in that assembly.");
  34:             return;
  35:         }
  36:         installer.Context = context;
  37:         if (uninstalling)
  38:             installer.Uninstall(mySavedState);
  39:         else
  40:             installer.Install(mySavedState);
  41:     }
  42:     catch (Exception e)
  43:     {
  44:         Console.WriteLine(e.Message);
  45:     }
  46:     return true;

47: }

Yes, that is managed code and unmanaged code *in the same function*!  Now this code might not compile as it is not what I wound up using and I just grabbed it out of an old folder but you get the idea (and yes I did test a version of this so I know the concept works).  I didn't use this approach because the /clr switch requires the dynamic CRT and I didn't feel like bundling that up.

And, in case you were wondering about the "boo" messagebox on line 3, that is my debugging trap.  You run the installer until that pops up, attach to the proper msiexec using Visual Studio, set a break point, and go.  Yup, that's cool.


Related posts

Comments

June 30. 2008 06:36 AM

steve

I don't understand posts like these ... you tell but ... then you don't really tell your solution. Mixed mode is something that is known ... what often is missing are details. If you don't provide details everything else is simply useless.

steve

Add comment


(Will show your Gravatar icon)  

  Country flag

[b][/b] - [i][/i] - [u][/u]- [quote][/quote]



Live preview

July 5. 2008 03:44 AM

Search

Tags

Don't show

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2008