Exposing a managed COM local server - E_NOINTERFACE

926 views Asked by At

Im trying to expose a local server that is written in C# to unmanaged code to allow interop! The managed code looks like that:


    [Guid("A0D470AF-0618-40E9-8297-8C63BAF3F1C3")]
    [ComVisible(true)]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IMyLocalInterface
    {
        void LogToServer(string message);
    }

    [Guid("9E9E5403-7993-49ED-BAFA-FD9A63A837E3")]
    [ComVisible(true)]
    [ClassInterface(ClassInterfaceType.None)]
    public class MyLocalClass : IMyLocalInterface
    {
        public MyLocalClass()
        {
            Console.WriteLine("Object created!");
        }

        public void LogToServer(string message)
        {
            Console.WriteLine("Log > " + message);
        }
    }

    class Program
    {
        [MTAThread]
        static void Main(string[] args)
        {
            var srv = new RegistrationServices();
            var cookie = srv.RegisterTypeForComClients(typeof(MyLocalClass), RegistrationClassContext.LocalServer | RegistrationClassContext.RemoteServer, RegistrationConnectionType.MultipleUse);

            Console.ReadLine();

            srv.UnregisterTypeForComClients(cookie);
        }
    }

And my unmanaged code does the following:


#import "ManagedLocServer.tlb" no_namespace raw_interfaces_only

int _tmain(int argc, _TCHAR* argv[])
{
    CoInitializeEx(NULL, COINIT_MULTITHREADED);
    {
        IMyLocalInterfacePtr ptr;
        ptr.CreateInstance(__uuidof(MyLocalClass));

        ptr->LogToServer(L"Initializing...");

    }
    CoUninitialize();
    return 0;
}

After debugging ive seen that CoCreateInstance works without any problems, that means "Object created" is printed into the managed servers console. But then QueryInterface on that object fails with E_NOINTERFACE. Im a bit confused why this happens. Is it a problem with registration (i only have a LocalServer32 entry for my CLSID)? Is it a problem within my managed code? Would be nice if someone could give me a hint :)

Greetings Joe

1

There are 1 answers

2
Hans Passant On

You are using out-of-process COM. That requires marshaling support, to make a method call the arguments of the method need to be serialized. That's normally done by building the proxy/stub DLL from the code generated by midl.exe from the .idl file. Or by using the standard marshaller which works with the type library. Both require registry entries in HKCR\Interface

You get the E_NOINTERFACE because COM cannot find a marshaller. This is trivial to solve if you have an .idl file but you don't, the server is implemented in .NET. No idea how to solve this, I never tried to make this work. A remote possibility is that the CLR interop layer provides marshaling support. But you'd surely at least have to use ComInterfaceType.InterfaceIsDual. This is just a guess. If I tried to make this work, I'd start from an .idl first.