2

I have a COM project which does not support MFC and needs to communicate with another App through a MFC interface. I cannot use directly in MFC interface with my COM project as it is not an MFC project.

A solution was to create an automation interface for the Of the MFC interface which I would be able to use as a layer through which my COM project can communicate to the MFC project.

As I understood, the automation app will run in a different thread. My COM project will invoke methods from the automation interface to call the MFC interface.

The Automation project and its IDL file were provided to me and provides me with a Pure Dispinterface.

Before integrating the implementation of the IDispatch interface to my COM project I decided to create a new C++ console project in order to focus on simply using the automation interface. Using the documentation provided by microsoft (https://learn.microsoft.com/en-us/previous-versions/windows/desktop/automat/implementing-the-idispatch-interface) I implemented the IDispatch interface as follows:

#include "TTAutomate.h"

HRESULT hresult;
DISPID dispid;
DISPPARAMS dispparamsNoArgs = { NULL, NULL, 0, 0 };
EXCEPINFO excepinfo;
UINT nArgErr;
ClassFromIDL* m_ClassFromIDL;
_DTTAutomateEvents* m_DTTAutomateEvents;
_DTTAutomate* m_DTTAutomate;


hresult = OleInitialize(NULL);

// OLE function CoCreateInstance starts application using GUID.
hresult = CoCreateInstance(CLSID_TTfromIDL, NULL, CLSCTX_INPROC_SERVER, DIID__DTTAutomateEvents, (LPVOID*)m_Automate);


// Call QueryInterface to see if object supports IDispatch.
hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL, (LPVOID*)pdisp);

// Retrieve the dispatch identifier for the SayHello method.
// Use defaults where possible.
OLECHAR* szMember = "SayHello";
DISPID dispid_Item;
hresult = pdisp->GetIDsOfNames(
    IID_NULL,
    &szFunction,
    1,
    LOCALE_USER_DEFAULT,
    &dispid_Item);

First of all the implementation is a bit different as the one in the documentation because with the line :

hresult = CoCreateInstance(CLSID_Hello, NULL, CLSCTX_SERVER, IID_IUnknown, (void **)&punk);

I would get an error "amp undefined".

With the code above I currently get an error stating a const char * cannot initialize a OLECHAR *.

On my COM project I have a line:

LPOLESTR szFunction = OLESTR("SayHello");

which compiles but the same line on my test project does not work.

Did I miss some includes to add? Did I not create the right kind of test project?

Andrew Truckle
  • 17,769
  • 16
  • 66
  • 164
firehelm
  • 49
  • 5
  • 1
    Test project is ok. But it's easier if you use ATL and CComPtr<> or IDispatchPtr or CComDispatchDriver or COleDispatchDriver. Search some of those terms especially the last two.They make it easier to drive a server object. – Joseph Willcoxson Jan 06 '21 at 23:22
  • @JosephWillcoxson, do you mean that I need to have an ATL project ? Because here I have a simple console App. I am looking into the other terms you suggested. – firehelm Jan 07 '21 at 13:17
  • So I did some fixes in that code and now it compiles, but in runtime I get a `REGDB_E_CLASSNOTREG Class not registered` at the call for `CoCreateInstance`. The fixes I did were : `IDispatch* m_Automate` `hresult = CoCreateInstance(CLSID_TTfromIDL, NULL, CLSCTX_INPROC_SERVER, DIID__DTTAutomateEvents, (void**)&m_Automate);`; `hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL, (void**)&pdisp);` and declaring the function name as a `wchar_t*` – firehelm Jan 07 '21 at 14:41
  • Why you don't communicate simply with Windows messages ? it more easy than automation – Landstalker Jan 07 '21 at 20:25
  • @Landstalker, the automation code was provided to me so I did not really chose to use automation. Yet I am new in Windows programming, what are windows messages ? Any interesting link to share ? – firehelm Jan 08 '21 at 10:06

1 Answers1

0

So I found a way to fix my code so that it compiles but not exactly sure if it is a proper solution:

#include "TTAutomate.h"
#include <string>

HRESULT hresult;
DISPID dispid;
DISPPARAMS dispparamsNoArgs = { NULL, NULL, 0, 0 };
EXCEPINFO excepinfo;
UINT nArgErr;
ClassFromIDL* m_ClassFromIDL;
IDispatch* m_Automate; // fixed


hresult = OleInitialize(NULL);

// OLE function CoCreateInstance starts application using GUID.
hresult = CoCreateInstance(CLSID_TTfromIDL, NULL, CLSCTX_INPROC_SERVER, DIID__DTTAutomateEvents, (void**)&m_Automate); // fixed


// Call QueryInterface to see if object supports IDispatch.
hresult = m_ClassFromIDL->QueryInterface(DIID__DTTfromIDL, (void**)&pdisp); // fixed

// Retrieve the dispatch identifier for the SayHello method.
// Use defaults where possible.

// here I create a wchar_t* variable as LPOESTR is casted from that.
std::string functionName = "SayHello";
int wchars_num = MultiByteToWideChar(CP_UTF8, 0, functionName.c_str(), -1, NULL, 0);
wchar_t* wstr = new wchar_t[wchars_num];

LPOLESTR szMember = wstr;
DISPID dispid_Item;
hresult = pdisp->GetIDsOfNames(
IID_NULL,
&szFunction,
1,
LOCALE_USER_DEFAULT,
&dispid_Item);

I now get a E_NOINTERFACE No such interface supported but it is probably unrelated to this topic.

firehelm
  • 49
  • 5