Предоставление управляемого локального сервера COM — E_NOINTERFACE

Я пытаюсь открыть локальный сервер, написанный на C #, для неуправляемого кода, чтобы разрешить взаимодействие! Управляемый код выглядит так:


    [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);
        }
    }

И мой неуправляемый код делает следующее:


#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;
}

После отладки увидел, что CoCreateInstance работает без проблем, значит "Объект создан" выводится в консоль управляемых серверов. Но затем QueryInterface для этого объекта завершается с ошибкой E_NOINTERFACE. Я немного смущен, почему это происходит. Это проблема с регистрацией (у меня есть только запись LocalServer32 для моего CLSID)? Это проблема в моем управляемом коде? Было бы неплохо, если бы кто-нибудь подсказал :)

Привет Джо


person Joe    schedule 02.02.2011    source источник


Ответы (1)


Вы используете внепроцессный COM. Это требует поддержки маршалинга, чтобы вызвать метод, аргументы метода должны быть сериализованы. Обычно это делается путем создания прокси/заглушки DLL из кода, сгенерированного midl.exe из файла .idl. Или используя стандартный маршаллер, который работает с библиотекой типов. Оба требуют записей реестра в HKCR\Interface

Вы получаете E_NOINTERFACE, потому что COM не может найти маршаллер. Это тривиально решить, если у вас есть файл .idl, но у вас его нет, сервер реализован в .NET. Не знаю, как это решить, я никогда не пытался заставить эту работу работать. Маловероятно, что уровень взаимодействия CLR обеспечивает поддержку маршалинга. Но вам наверняка придется использовать ComInterfaceType.InterfaceIsDual. Это всего лишь предположение. Если бы я попытался сделать эту работу, я бы сначала начал с .idl.

person Hans Passant    schedule 02.02.2011
comment
Может быть, он мог бы попытаться использовать regasm /tlb для создания библиотеки типов, а затем зарегистрировать эту библиотеку типов в реестре и, таким образом, бесплатно получить автоматизацию сортировки? - person sharptooth; 02.02.2011
comment
@sharp - я не знаю, этот инструмент долгое время был в свободном доступе. Он вернулся в .NET 4.0 под именем regtlibv12.exe, по крайней мере, на моей машине. Никаких документов вообще, даже /? помогите, я не знаю, что он делает. Я ожидаю, что он будет писать в HKCR\TypeLib, но запись необходимых записей в HKCR\Interface кажется мне крайне маловероятной, поскольку это может испортить существующую регистрацию. - person Hans Passant; 02.02.2011