COM registration if you need a typelib
The problem with the previous examples I posted on minimal COM object registration is that they don't always work. As I mentioned, if you follow the rules specified, while your COM object will work just fine from Win32 applications, you'll have problems if you attempt to access it from a managed environment (either an app running under the CLR or another management environment such as the VB6 runtime or the scripting host).
For those environments, you need to have a typelib. Since typelib's were designed primarily for interoperating with visual basic, they don't provide full access to the functionality that's available via MIDL (for instance, unnamed unions get turned into named unions, the MIDL boolean type isn't supported, etc), but if you gotta interoperate, you gotta interoperate.
So you've followed the examples listed here and you've registered your COM object, now how do you hook it up to the system?
First, you could call the RegisterTypeLib function, which will perform the registration, but that would be cheating :) More importantly, there are lots of situations where it's inappropriate to use RegisterTypeLib - for instance, if you're building an app that needs to be installed, you need to enumerate all the registry manipulations done by your application so they can be undone.
So if you want to register a typelib, it's a smidge more complicated than registering a COM component or interface.
To register a typelib, you need (from here):
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\
Default Value: <friendly name for the library> Again, not really required, but nice for oleview
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\HELPDIR
Default Value: <Directory that contains the help file for the type library>
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\FLAGS
Default Value: Flags for the ICreateTypeLib::SetLibFlags call (typically 0)
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\<LCID for library>
Key: HKEY_CLASSES_ROOT\Typelib\<LibID>\<major version>.<minor version>\<LCID>\<Platform>
Default Value: <File name that contains the typelib>
Notes:
If your typelib isn't locale-specific, you can specify 0 for the LCID. Looking at my system, that's typically what most apps do.
<Platform> can be win32, win64 or win16 depending on the platform of the binary.
But this isn't quite enough to get the typelib hooked up - the system still doesn't know how to get access to the type library. To do that, you need to enhance your CLSID registration to let COM know that there's a typelib available. With the typelib, a managed environment can synthesize all the interfaces associated with a class. To do that, you enhance the class registration:
Key: HKEY_CLASSES_ROOT\CLSID\<CLSID>\TypeLib = <LibID>
But we're still not quite done. For each of the interfaces in the typelib, you can let the system do the marshaling of the interface for you without having to specify a proxy library. To do this, you can let the standard proxy marshaler do the work. The universal marshaler has a clsid of {00020424-0000-0000-C000-000000000046}, so instead of using the interface registration mentioned in the last article, you can replace it with:
Key: HKEY_CLASSES_ROOT\Interface\<IID>\
Default Value: <friendly name for the interface> Again, not really required, but nice for oleview
Key: HKEY_CLASSES_ROOT\Interface\<IID>\ProxyStubClsid32\
Default Value: {00020424-0000-0000-C000-000000000046}
Key: HKEY_CLASSES_ROOT\Interface\<IID>\TypeLib\
Default Value: <LibID>
Now instead of using the proxy code in a proxy DLL, the system will do the marshaling for you.
Next: Ok, but what if I don't want to deal with all those ugly GUID thingies?
Comments
- Anonymous
January 09, 2006
If you're calling from .NET, then I didn't think you needed to actually register the typelib. Just use tlbimp.exe in a type library file and it generates the RCW - it doesn't use the type library at runtime.
Even from the Visual Studio IDE, if you select the COM tab in "Add Reference", it lists all the registered type libraries, but you can also Browse for one that's not actually registered... - Anonymous
January 09, 2006
"More importantly, there are lots of situations where it's inappropriate to use RegisterTypeLib - for instance, if you're building an app that needs to be installed, you need to enumerate all the registry manipulations done by your application so they can be undone."
What's wrong with UnRegisterTypeLib? The name seems to indicate it should do the job--or is there some catch? Raymond rails against developers who grunge in the registry when they should be using documented interfaces, and I don't want him to holler at me. :) - Anonymous
January 09, 2006
The comment has been removed - Anonymous
January 09, 2006
Is the LCID specified in hex or decimal? (ie: 1033 or 409 for english)? - Anonymous
January 09, 2006
The comment has been removed - Anonymous
January 10, 2006
Thank you mirobin.
Btw, I don't know if the LCID is decimal or hex. I suspect hex, but I didn't find any examples when I went looking yesterday - Anonymous
January 10, 2006
The MSI way to register COM server is the Class table, and the associated AppId table. I don't know if they support everything the COM registration requires, though. - Anonymous
January 10, 2006
Yeah, it's hex. So it would be:
HKEY_CLASSES_ROOTTypelib<LibID><major version>.<minor version>409
or whatever...