C# IConnectionPointContainer.FindConnectionPoint throws exception

0

I am trying to implement an ATL COM module with a connection point. The source code for this is all pretty much boilerplate that I copied by example from chapter 12 of Developer's Workshop to COM and ATL 3.0 by Andrew W. Troelsen.

That's a lot of code, with three source files (almost all Visual Studio rendered boilerplate).

I think have got everything that I need, though. There is a subclass called _IFooEvents_CP.h to handle events and the class implemments 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
     //...
     }

}

Then, in the header to my coclass (Foo, of course):

// 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()

Furthermore, the idl file has the event source forward declared and all set thanks to the ATL connection point wizard that I used to make this thing:

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

So, I have an implementation of the connection point container interface, I have a connection point in the connection point map, and I have forward declared an event function to implement on the client side.

It compiles without warning or error. Then on the C# side I have the following:

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

The exception is thrown on this line:

 icpc.FindConnectionPoint(ref id, out icp);

and the error code is exotic: 0x80040200. I couldn't locate this code anywhere, but I think it is not an official Windows code. At least, I couldn't find it on MSDN's list.

I copied the client code from an example I found online, so it could be that I am missing a step.

Later: As @Hans Passant pointed out, the error code is CONNECT_E_NOCONNECTION. My understanding is that this means that there are no connections exposed by the interface. But, as far as I can tell (and I am new to this game) I have done everything I need to do in order to have an outgoinginterface here.

I feel like I'm missing some tiny magical step.

c#
callback
com
atl
asked on Stack Overflow May 29, 2017 by dmedine • edited May 29, 2017 by dmedine

0 Answers

Nobody has answered this question yet.


User contributions licensed under CC BY-SA 3.0