C# IConnectionPointContainer.FindConnectionPoint выдает исключение

Я пытаюсь реализовать модуль ATL COM с точкой подключения. Исходный код для этого является в значительной степени образцом, который я скопировал на примере из главы 12 Семинара разработчика для COM и ATL 3.0 Эндрю У. Троелсена.

Это много кода с тремя исходными файлами (почти все визуализировано в Visual Studio).

Я думаю, что есть все, что мне нужно. Существует подкласс _IFooEvents_CP.h для обработки событий, и класс реализует IConnectionPointImpl: using namespace ATL;

template <class T>
class CProxy_IFooEvents : public IConnectionPointImpl<T, &__uuidof( _IFooEvents ), CComDynamicUnkArray>
{
    // WARNING: This class may be regenerated by the wizard
public:
        HRESULT Fire()
     {
     //...
     // event proxy code
     //...
     }

}

Затем в шапке моего кокласса (Фу, конечно):

// Foo.h : Declaration of the CFoo

#pragma once
#include "resource.h"       // main symbols



#include "ConnectionPointTest_i.h"
#include "_IFooEvents_CP.h"



#if defined(_WIN32_WCE) && !defined(_CE_DCOM) && !defined(_CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA)
#error "Single-threaded COM objects are not properly supported on Windows CE platform, such as the Windows Mobile platforms that do not include full DCOM support. Define _CE_ALLOW_SINGLE_THREADED_OBJECTS_IN_MTA to force ATL to support creating single-thread COM object's and allow use of it's single-threaded COM object implementations. The threading model in your rgs file was set to 'Free' as that is the only threading model supported in non DCOM Windows CE platforms."
#endif

using namespace ATL;


// CFoo

class ATL_NO_VTABLE CFoo :
    public CComObjectRootEx<CComSingleThreadModel>,
    public CComCoClass<CFoo, &CLSID_Foo>,
    public IConnectionPointContainerImpl<CFoo>,
    public IDispatchImpl<IFoo, &IID_IFoo, &LIBID_ConnectionPointTestLib, /*wMajor =*/ 1, /*wMinor =*/ 0>,
    public CProxy_IFooEvents<CFoo>
{
public:
    CFoo()
    {
    }

DECLARE_REGISTRY_RESOURCEID(IDR_FOO)


BEGIN_COM_MAP(CFoo)
    COM_INTERFACE_ENTRY(IFoo)
    COM_INTERFACE_ENTRY(IDispatch)
    COM_INTERFACE_ENTRY(IConnectionPointContainer)
END_COM_MAP()

BEGIN_CONNECTION_POINT_MAP(CFoo)
    CONNECTION_POINT_ENTRY(__uuidof(_IFooEvents))
END_CONNECTION_POINT_MAP()

Кроме того, в файле idl объявлен источник пересылки событий и все настроено благодаря мастеру точек подключения ATL, который я использовал для создания этой вещи:

library ConnectionPointTestLib
{
    importlib("stdole2.tlb");
    [
        uuid(25EAB56B-884A-4AA9-B470-BAA975E08343)      
    ]
    dispinterface _IFooEvents
    {
        properties:
        methods:
            [id(1), helpstring("test")] HRESULT bar();
    };
    [
        uuid(54B6050F-1090-4660-9DF0-D8A0853F96CF)      
    ]
    coclass Foo
    {
        [default] interface IFoo;
        [default, source] dispinterface _IFooEvents;
    };
};

Итак, у меня есть реализация интерфейса контейнера точки подключения, у меня есть точка подключения на карте точек подключения, и я заранее объявил функцию события для реализации на стороне клиента.

Компилируется без предупреждения или ошибки. Тогда на стороне C# у меня есть следующее:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;
using System.Runtime.InteropServices.ComTypes;
using System.Runtime.InteropServices;
using ConnectionPointTestLib;

namespace TestConnectionPoint
{
    class EventSink
    {
        public EventSink() { }
        public void bar()
        {
            Console.WriteLine("hello");
            Console.ReadLine();
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            try
            {

                ConnectionPointTestLib.IFoo cpTest = new ConnectionPointTestLib.Foo();

                IConnectionPointContainer icpc;
                icpc = (IConnectionPointContainer)cpTest;
                IConnectionPoint icp;
                Guid id = typeof(Foo).GUID;

                icpc.FindConnectionPoint(ref id, out icp);


                EventSink es = new EventSink();
                int cookie;
                icp.Advise(es, out cookie);

                cpTest.testCP();
                Console.ReadLine();
            }
            catch (COMException e)
            {
                Console.WriteLine(e);
                Console.ReadLine();
            }
        }
    }
}

Исключение выдается в этой строке:

 icpc.FindConnectionPoint(ref id, out icp);

и код ошибки является экзотическим: 0x80040200. Я не мог найти этот код в любом месте, но я думаю, что это не официальный код Windows. По крайней мере, я не смог найти его в списке MSDN.

Я скопировал код клиента из примера, который нашел в Интернете, так что, возможно, я пропустил шаг.

Позже: как отметил @Hans Passant, код ошибки - CONNECT_E_NOCONNECTION. Насколько я понимаю, это означает, что интерфейс не предоставляет никаких соединений. Но, насколько я могу судить (и я новичок в этой игре), я сделал все, что мне нужно, чтобы иметь здесь исходящий интерфейс.

Я чувствую, что пропустил какой-то крошечный магический шаг.

0 ответов

Другие вопросы по тегам