Replicating Visual Studio COM registration with a

2019-01-13 13:20发布

问题:

Once upon a time, a young, naive engineer thought it would be a good idea to separate out some of the functionality for his app into a COM component, written in C#. Visual studio had all the tools to do that, right? .NET was practically made for this, right? HA! He said, this will be easy. I'll have decent separation of components, keeping business logic away from the front end, and with COM, I'll be able to use it from anywhere! He merrily checked the register for COM interop checkbox in the project properties, exposed the classses he wanted, and went on his way.

Oh, the trials such a choice made. The young engineer now, more experienced, would not now wish this upon anyone. However, the burden had been placed upon his shoulders, and the burden remained heavy. He looked to lighten the load.

Along came WiX, a tool for generating Windows Installer files from XML. This intrigued him - it could replicate, quite simply, most of the code needed for a proper windows installer file simply from a handful of configuration files. His sights were looking up.

With WiX 2.0, he could generate quite easily the files needed to register a C# COM object. This involved using the tool tallow. He'd do something like the following:

tallow -c -nologo MyComExposedLibrary.dll > MyComExposedLibrary.wxs

which would then be fixed up (at first this was done manually, but eventually I recorded the steps into a small tool set the final directory ref id, component ID, fileID, GUID and codebase).

Then, the ensuing installer would install, and there would be joyous celebration, if the app worked.

Which it did not.

For days the young engineer poured over the differences on his development PC and that of the test install PC. "All the registry keys are the same!" He would exclaim. "Everything for MyComExposedLibrary is registerd, I swear!"

Except, it wasn't.

On the dawn of third day, after many a mountain dew, he realized there was one more object that Visual Studio was registering that his installer was not: the MyComExposedLibrary.tlb file.

Visual Studio, apparently, had been registering this file all along, creating additional subkeys in the HKLM\Software\Classes\Interface registry key, and registering the typelib in HKLM\SOFTWARE\Classes\TypeLib.

Tallow gave no help, complaining that a .tlb wasn't a file it groked. Nor the WiX 3.0 beta - this seemed to have even more issues getting things working.

I also gave Heat a try. This generated registry elements and class elements. I cleaned up heat's output, and then went to compile it, but got a different error: error LGHT0130 : The primary key <uuid here> is duplicated in table 'Registry'. Problem is, as far as I can tell, that uuid doesn't actually exist in any of my wxs source files. If I change around the component ref order in my feature element, a different dll component gives that error. Since I have been unsuccessful at getting a WiX 3.0 version of the project to compile, I haven't been able to confirm whether or not heat gives the right output.

I removed everything from the installer except for one of the assembly that cause this error to appear and tried compiling again. I got the same same error. Arrugh!

So, my good fellows, Windows enthusiasts, and WiX users, there falls two questions:

  • Is a typelib something that WiX can register natively? If so, how?
  • If not, what's the proper way of registering a typelib with a windows installer?

Also, I guess as another part of this, how does Visual Studio determine how to register the typelib? (Edit: looks the MSDN library article on typelib registration has the names of the keys needed, but I still need to figure out how to get the uuid's. (This is from this blog post on typelib and COM registration by Larry Osterman.) ) Reading a bit more, It may fall to me to register these bits manually, but I hope not...

I evaluated the output from regasm /regfile:MyDll.dll MyDll.dll. It looks like these are the same keys that wix generates for the dll. Regasm's other mode, regasm /tlb:<filename> generates and registers the typelib for the assembly, but,

/regfile[:FileName] Generate a reg file with the specified name instead of registering the types. This option cannot be used with the /u or /tlb options

seems the /regfile switch is incompatible with the /tlb switch. Khaaaaaaaan!

Further update: It looks like you don't actually need to include the .tlb file. According to this post on wix's typelib element, an MSI can create/register this as part of the setup process. It all comes down to configuring the WiX document to actually install it by getting the right attributes.

I found out later that you can get the right attributes using heat on the .tlb directly! See this SO question for more information.

回答1:

You should use Heat (WIX 3.0) located in the bin directory of the version you are using. Have a look at this blog post, we use it here to register all our COM objects, by creating a wix fragment...

something like

heat file MyComExposedLibrary.dll -out MyComExposedLibrary.wxs

After, reading your edit, I would create a basic msi with wix that installs the com object only, see if that works ... then you'll know which battlefield to attack ...



回答2:

I recently ran into this issue, and the simplest workaround I could find follows these steps on the development machine:

  1. Run: Regasm MyDLL.dll /tlb:MyDLL.tlb
  2. Run: Heat file MyDLL.dll -out MyDll-1.wxs
  3. Run: Heat file MyDll.tlb -out MyDll-2.wxs

MyDll-2.wxs contains a <Typelib> element that you will want to copy and nest inside the <File> element that was generated in MyDll-1.wxs. This will give you a complete <Component> element that you can use in the installer project.



回答3:

To extract the COM information, tallow will use the regasm.exe tool included with the .NET framework. It is likely that visual studio uses the same tool to register assemblies when you enable "register for COM interop".

The difference is that tallow will use the regasm /regfile switch to send the information to a .reg file instead of actually registering the assembly. Unfortunately the .reg file generated by regasm.exe is not complete. It skips the typelib entries which it does write to the registry during a real registration. This may be a bug in regasm.

To get your installer working you have three options:

  1. Add the missing registry keys to the tallow output manually. The tallow output is intended to be edited manually and saved along with your other wxs files anyway. You seem to be trying to fully automatically generate a working wxs file but I believe that was never a design goal of tallow.

  2. Use a custom action to invoke regasm from your installer. This is slightly evil because you may lose some of the strong transactional guarantees provided by the windows installer engine. I'm thinking of rollbacks triggered by a failure halfway during the install here.

  3. Avoid the registration altogether by making use of registration-free COM. This will require the creation of manifest files for both the application and the COM library.



回答4:

I know this is an older question, but others may find this useful...

After struggling with this myself, I found that you can capture the type library information by using tlbexp.exe then heat both the dll and the tlb file. Include the outputs of both of those in your wix project and you should be good to go.

tlbexp.exe dllFile.dll /out:dllFile.tlb
heat.exe dllFile.dll ...
heat.exe dllFile.tlb ...