views:

119

answers:

1

I am trying to register a winform user control as a COM Server so my MFC applications can use them. The winform control is written in C++/CLI and uses an unmanaged native dll. I want to make use of .net's terrific Interop services to register this user control as a COM server.

[ProgId("MyAx.MyAxControl")]    
[ClassInterface(ClassInterfaceType::AutoDual)]
[Guid("612EAF58-ADCC-4e87-BC9E-FA208B037414")]
public ref class MyAxControl: public System::Windows::Forms::UserControl

MSDN said I can use regasm to achieve what I am doing, so I went ahead and registered it

regasm MyAx.dll /tlb:MyAx.tlb

I even generated a registry entry

regasm MyAx.dll /regfile:MyAx.reg

and merged it with my registry

At this point I had expected that this control will show up in my COM Components when I go choose Items for the tool box. However it ain't showing up there. Is this an expected behavior ?. If yes, how will I use this control in my MFC application, for that matter any language that consumes an Activex control (say Java).

+1  A: 

Hi

What you are missing is telling the system your COM object is a control. The missing information is "Implemented Categories" entry in the registry. To provide this info during the registration to COM so you will need to create custom COM (un)registration function.

private const string ControlsCategoryId = "{40FC6ED4-2438-11CF-A3DB-080036F12502}";

[ComRegisterFunction]
internal static void ComRegister(string key)
{
    key = key.Replace("HKEY_CLASSES_ROOT\\", "");
    RegistryKey reg = Registry.ClassesRoot.CreateSubKey(key);
    reg.SetValue("", "Your.ProgId.Here");
    reg = reg.CreateSubKey("Implemented Categories");
    reg.CreateSubKey(ControlsCategoryId);
}

[ComUnregisterFunction]
internal static void ComUnregisterFunction(string key)
{
    key = key.Replace("HKEY_CLASSES_ROOT\\", "");
    RegistryKey reg = Registry.ClassesRoot.OpenSubKey(key, true);
    reg = reg.OpenSubKey("Implemented Categories", true);
    reg.DeleteSubKey(ControlsCategoryId);
}

Com (un)registration routines have to be static, returning void, accepting single string or Type argument, and have appropriate attribute. The MSDN now claims that only Type argument is accepted, but for compatibility reasons the string version (from version 1.1) is working too. The string passed to this function is registry key HKCR\CLSID{YOUR-CLASS_GUID}.

Hope that helps.

kossib
I had it already in my code. Well took some of your advise to implement it like you just did. But its not showing up in the COM Components when you try add it through choose items.
rptony
It seems that although you set the ProgId, the COM component is listed by the full type name (full namespace and typename) rather than by that ProgId. It is however creatable by that ProgId. I've updated the code withreg.SetValue("", "Your.ProgId.Here");and now it should display correctly in the COM Components (also in OLE Viewer under the Objects\Groupped By Category\Controls)
kossib