Accessing VB activeX exe from VC++

Hi,

I have an activeX exe written in VBasic.
I need to access this from Visual C++.
How do I do this ?
Any sample code will be of great help.

Thank you.
kkandasaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

kkandasaAuthor Commented:
P.S

The Visual C++ app is a console application with MFC support.

Thanks.
0
Brain2000Commented:
It's been a while since I've done this, but this should do the trick.  I created a control called "Vicnet".  Here's how I accessed it with a C interface.  The function CoCreateInstance() does all the work if I recall correctly.

Note: The header files listed here are what I used.  You'll have to make sure you generate the appropriate .h files from the typelibrary file (.tlb) using mktyplib.exe.

#define INITGUID

#include <stdio.h>
#include <objbase.h>
#include <winuser.h>
#include "VicNetCTL.h"
#include "VicNetGuids.h"
#include "VicNetPPG.h"

void main(void)
{
  //IVicNet is created by from .tlb
  //file using mktyplib.exe
  IVicNet *lpVicNet;
  IOleControl *lpOleObject;
  HRESULT hr;

  hr=CoInitialize(NULL);
  if(FAILED(hr)) {
    MessageBox(NULL,"COINIT Failed?",
      "DEBUG",MB_OK);
    return;
  }
  hr=CoCreateInstance(
      CLSID_VicNet,
      NULL,
      CLSCTX_INPROC_SERVER,
      IID_IVicNet,
      (void **)&lpVicNet);
  if(FAILED(hr)) {
    char temp[100];
    sprintf(temp,"ERR COCREATEIN: 0x%x",
      hr);
    MessageBox(NULL,temp,"DEBUG",MB_OK);
    CoUninitialize();
    return;
  }
  MessageBox(NULL,"CREATED CO INSTANCE",
    "DEBUG",MB_OK);

  //at this point, one of the methods
  //requires a phone number to be
  //sent to it.  Here's how I call it
  unsigned short bstr[10];
  MultiByteToWideChar(
    CP_ACP,
    NULL,
    "555-1212",
    10,
    (LPWSTR)&bstr,
    sizeof(bstr));
  lpVicNet->put_Phone1(bstr);
  lpVicNet->Dial();
  CoUninitialize();
}
0
kkandasaAuthor Commented:
Thank you very much for the info.

I do have a couple of questions from
the sample code you provided. I am
new to this, so please bear with me.


  //IVicNet is created by from .tlb
  //file using mktyplib.exe
  IVicNet *lpVicNet;

I used VC++ to import the vbasic type
library. I got the .cpp and .h files.

Where do I get the equivalent of CLSID_VicNet, IID_IVicNet, IVicNet * ?

Could you post sample of the header
and cpp file ?

Thanks.
0
Cloud Class® Course: CompTIA Cloud+

The CompTIA Cloud+ Basic training course will teach you about cloud concepts and models, data storage, networking, and network infrastructure.

kkandasaAuthor Commented:
Hello,

One more question.

When using a VBapp, I invoke the
activeX exe the following way:

-------------
Set PHandle(i) = CreateObject(LCPath)
'Then raise event to allocate the line
RaiseEvent PHandle(i).startline(i)
----------

How can I RaiseEvent in VC++ when
invoking the ActiveX exe ?


Thanks.
0
Brain2000Commented:
Posted below is part of one of the header files called VicNetInterfaces.h.  This file is automatically created by mktyplib.

How do you use the event sync in C?  I've never actually done this, so I can't give you source code.  However, I believe I understand the theory, so here it goes.  There is another class declared in VicNetInterfaces.h called DVicNetEvents.  This class must be derived into a new class.  Each event will have its own C++ function that you can create in this new class.  When that event fires, it will call your function.  Take a look below, you will see that I have two events in my VicNet control.  When the phone is hung up, and when it's picked up.

By now, you've probably figured out that my VicNet control is used for public kiosk applications that have a telephone handset.  The control takes care of dialing and connecting a person with their destination, without the user needing to dial the number.  Not that people can't dial numbers, it's just that we can't have people dialing England, now can we?


#ifndef _VicNetObjects_H_
#define _VicNetObjects_H_

DEFINE_GUID(
  LIBID_VicNetObjects,
  0xB6A9CDE2L,
  0x2927,0x11D1,
  0x9F,0xC7,0xAB,0x95,
  0xC4,0xEF,0x9B,0x43);
#ifndef BEGIN_INTERFACE
#define BEGIN_INTERFACE
#endif

DEFINE_GUID(
  IID_IVicNet,
  0xB6A9CDE3L,
  0x2927,0x11D1,
  0x9F,0xC7,0xAB,0x95,
  0xC4,0xEF,0x9B,0x43);

DEFINE_GUID(
  CLSID_VicNet,
  0xB6A9CDE5L,
  0x2927,0x11D1,
  0x9F,0xC7,0xAB,0x95,
  0xC4,0xEF,0x9B,0x43);

#define INTERFACE IVicNet

DECLARE_INTERFACE_(IVicNet, IDispatch)
{
BEGIN_INTERFACE
#ifndef NO_BASEINTERFACE_FUNCS

    /* IUnknown methods */
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
    STDMETHOD_(ULONG, Release)(THIS) PURE;

    /* IDispatch methods */
    STDMETHOD(GetTypeInfoCount)(THIS_ UINT FAR* pctinfo) PURE;

    STDMETHOD(GetTypeInfo)(
      THIS_
      UINT itinfo,
      LCID lcid,
      ITypeInfo FAR* FAR* pptinfo) PURE;

    STDMETHOD(GetIDsOfNames)(
      THIS_
      REFIID riid,
      OLECHAR FAR* FAR* rgszNames,
      UINT cNames,
      LCID lcid,
      DISPID FAR* rgdispid) PURE;

    STDMETHOD(Invoke)(
      THIS_
      DISPID dispidMember,
      REFIID riid,
      LCID lcid,
      WORD wFlags,
      DISPPARAMS FAR* pdispparams,
      VARIANT FAR* pvarResult,
      EXCEPINFO FAR* pexcepinfo,
      UINT FAR* puArgErr) PURE;
#endif

    /* IVicNet methods */
    STDMETHOD(get_Phone1)(THIS_ BSTR FAR* number) PURE;
    STDMETHOD(put_Phone1)(THIS_ BSTR number) PURE;
    STDMETHOD(get_Phone2)(THIS_ BSTR FAR* number) PURE;
    STDMETHOD(put_Phone2)(THIS_ BSTR number) PURE;
    STDMETHOD(get_Phone3)(THIS_ BSTR FAR* number) PURE;
    STDMETHOD(put_Phone3)(THIS_ BSTR number) PURE;
    STDMETHOD(get_Phone4)(THIS_ BSTR FAR* number) PURE;
    STDMETHOD(put_Phone4)(THIS_ BSTR number) PURE;
    STDMETHOD(get_VicNetComm)(THIS_ BSTR FAR* port) PURE;
    STDMETHOD(put_VicNetComm)(THIS_ BSTR port) PURE;
    STDMETHOD(get_ModemComm)(THIS_ BSTR FAR* port) PURE;
    STDMETHOD(put_ModemComm)(THIS_ BSTR port) PURE;
    STDMETHOD(get_VicNetTimeout)(THIS_ BSTR FAR* sec) PURE;
    STDMETHOD(put_VicNetTimeout)(THIS_ BSTR sec) PURE;
    STDMETHOD(Dial)(THIS) PURE;
    STDMETHOD(HangUp)(THIS) PURE;
    STDMETHOD_(void, AboutBox)(THIS) PURE;
};

DEFINE_GUID(DIID_DVicNetEvents,0xB6A9CDE4L,0x2927,0x11D1,0x9F,0xC7,0xAB,0x95,0xC4,0xEF,0x9B,0x43);

/* Definition of dispatch interface: DVicNetEvents */
#undef INTERFACE
#define INTERFACE DVicNetEvents

DECLARE_INTERFACE_(DVicNetEvents, IDispatch)
{
BEGIN_INTERFACE
#ifndef NO_BASEINTERFACE_FUNCS

    /* IUnknown methods */
    STDMETHOD(QueryInterface)(THIS_ REFIID riid, LPVOID FAR* ppvObj) PURE;
    STDMETHOD_(ULONG, AddRef)(THIS) PURE;
    STDMETHOD_(ULONG, Release)(THIS) PURE;

    /* IDispatch methods */
    STDMETHOD(GetTypeInfoCount)(THIS_ UINT FAR* pctinfo) PURE;

    STDMETHOD(GetTypeInfo)(
      THIS_
      UINT itinfo,
      LCID lcid,
      ITypeInfo FAR* FAR* pptinfo) PURE;

    STDMETHOD(GetIDsOfNames)(
      THIS_
      REFIID riid,
      OLECHAR FAR* FAR* rgszNames,
      UINT cNames,
      LCID lcid,
      DISPID FAR* rgdispid) PURE;

    STDMETHOD(Invoke)(
      THIS_
      DISPID dispidMember,
      REFIID riid,
      LCID lcid,
      WORD wFlags,
      DISPPARAMS FAR* pdispparams,
      VARIANT FAR* pvarResult,
      EXCEPINFO FAR* pexcepinfo,
      UINT FAR* puArgErr) PURE;
#endif

    /* DVicNetEvents methods:
    void OnPhoneUp(void);
    void OnPhoneDown(void);
    */
};

#ifdef __cplusplus
class VicNet;
#endif

#endif
0
kkandasaAuthor Commented:
Hi,

I have provided below the header file
that was generated for me by adding
a class by importing from a type
library in Visual studio. It looks
different from what your header file.

1) I need to call CoGetClassObject to
create objects on ActiveX. This requires
I know the CLSID & RFIID. Where would
I get this from the header file below ?

=================================
// Machine generated IDispatch wrapper class(es) created with ClassWizard
/////////////////////////////////////////////////////////////////////////////
// _PLineController wrapper class

class _PLineController : public COleDispatchDriver
{
public:
      _PLineController() {}            // Calls COleDispatchDriver default constructor
      _PLineController(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
      _PLineController(const _PLineController& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}

// Attributes
public:

// Operations
public:
      CString GetMonitorData();
      void SetMonitorData(LPCTSTR lpszNewValue);
      short F_Utility(BSTR* para);
      VARIANT Channel_Register(short* chtype, BSTR* sdata);
      short F_MonitorCaller(BSTR* para);
      VARIANT Channel_GetDetails(short* ch, BSTR* chdata);
      VARIANT CheckAppTimeout();
      VARIANT LC_UnRegisterSourceCaller();
      void LC_CheckForEvents();
      VARIANT LC_HandleEvents(BSTR* recvdmsg);
      VARIANT LC_SendLiveConnectMsg(BSTR* RegMode, BSTR* SrcType, BSTR* TarType, short* TarChan, short* AttemptMode);
      VARIANT LC_SendWaitForEvents();
      VARIANT LC_RegisterSourceCaller(BSTR* RegisterMode);
      VARIANT LC_SendTargetCallerMsg(BSTR* msg);
      VARIANT LC_StopWaitForEvents();
      void StopLine();
      void StopActivity();
      VARIANT PlayCharacter(BSTR* CToPlay);
      short PlaySystemMessage(BSTR* sfile);
      VARIANT PlayCurrency(double* CNo);
      VARIANT PlayDate(BSTR* DDate);
      VARIANT PlayNumber(double* NoToPlay);
      short PlayOrdinal(double* NoToPlay);
      short PlayNonDecimalNumber(double* NoToPlay);
      VARIANT Answercall();
      void Initialize_Call_Info();
      CString FormatDuration(long* dur);
      void Log_Call();
      // method 'Seperate_Parameters' not emitted because of invalid return type or parameter type
      short Get_Dnis_Info();
      short Get_Channel_Info();
      short Get_App_Call_Flow_Info(short* stepno);
      short Get_License_Info();
      CString UpdateAniBlock(long* callmins);
      CString CheckAniBlock();
      void Log_Error(BSTR* errtype, BSTR* errtext);
      short perform_function(BSTR* f, BSTR* p);
      short F_FaxSubmit(BSTR* para);
      short F_PlayVoiceFile(BSTR* para);
      short F_RotationalPlay(BSTR* para);
      short F_FileUtils(BSTR* para);
      short F_RecordVoiceFile(BSTR* para);
      short F_GruntDetection(BSTR* para);
      short F_DB_Request1(BSTR* para);
      short F_DirectSQL(BSTR* para);
      short F_StoredProc(BSTR* para);
      short F_DB_Request(BSTR* para);
      short F_Menu(BSTR* para);
      short Execute_App(short* curr_step);
      short F_Chat(BSTR* para);
      short Chat_Analog(BSTR* para);
      short Chat_Digital(BSTR* para);
      short F_GetDigits(BSTR* para);
      void ReadConfigFile();
      CString TakeOutFromString(LPCTSTR sourcestr, LPCTSTR TakeOutStr);
      void WriteTraceFile(BSTR* TLEVEL, BSTR* errtext);
      void WriteToFile(BSTR* fname, BSTR* errtext);
      short F_Compare(BSTR* para);
      short F_CreditCard(BSTR* para);
      short F_MultiCompare(BSTR* para);
      short F_AppTimeout(BSTR* para);
      short F_InvokeFlow(BSTR* para);
      short F_WaitForEvents(BSTR* para);
      short F_VoiceVerifier(BSTR* para);
      short VV_HandleRecvdData(BSTR* msg, double* Vscore, BSTR* Vfile);
      short F_LC_Setup(BSTR* para);
      short F_LC_Actions(BSTR* para);
      short F_SendRecvMsg(BSTR* para);
      short F_Email(BSTR* para);
      short F_Pickup(BSTR* para);
      short F_PreHangup(BSTR* para);
      short F_MonitorDisplay(BSTR* para);
      short F_CallOut(BSTR* para);
      short F_ParseData(BSTR* para);
      void Run_Outbound_App();
      void StartLine(short* Chan);
      void ResetLine();
      void SetupLineMode();
      short F_Transfer(BSTR* para);
      short F_Dial(BSTR* para);
      short F_Math(BSTR* para);
      CString ReturnValue(BSTR* parm);
      void Log_Event(BSTR* loglocation, BSTR* funcname, BSTR* lstring);
      short SetupLine();
};
/////////////////////////////////////////////////////////////////////////////
// __PLineController wrapper class

class __PLineController : public COleDispatchDriver
{
public:
      __PLineController() {}            // Calls COleDispatchDriver default constructor
      __PLineController(LPDISPATCH pDispatch) : COleDispatchDriver(pDispatch) {}
      __PLineController(const __PLineController& dispatchSrc) : COleDispatchDriver(dispatchSrc) {}

// Attributes
public:

// Operations
public:
      void StartLine(short* Chan);
      void StopLine();
      void ResetLine();
      void StopActivity();
};
====================================

0
Brain2000Commented:
Ahhh yes, I forgot.  This gets even more ugly. I haven't found a pretty way to get the UUID from a VB ActiveX object.  But here's what I do.  First, register your .OCX file using:

regsvr32.exe <filename.ocx>

Then, you need to make an HTML page that embeds an ActiveX object in it.  The best way is to use an HTML layout program.  Insert your ActiveX control and then view the HTML source.  You'll see something like this:

<object ID="VicNet"
CLASSID="clsid:B6A9CDE5-2927-11D1-9FC7-AB95C4EF9B43"
.........

At this point, you can then use the numbers above to create a header file with this line:

DEFINE_GUID(
  CLSID_VicNet,
  0xB6A9CDE5L,
  0x2927,0x11D1,
  0x9F,0xC7,0xAB,0x95,
  0xC4,0xEF,0x9B,0x43);
0
kkandasaAuthor Commented:
Hi,

I tried the follwing based on my header file.

----------------------
__PLineController *pLineCont;
pLineCont = new __PLineController;      
pLineCont->StartLine((short *)&iLoopIndex);
------------------

Nothing crashed but the ActiveX exe did not get invoked either.

0
Brain2000Commented:
Try this instead:

__PLineController *pLineCont;
CoCreateInstance(
      CLSID_LineCont,
      NULL,
      CLSCTX_INPROC_SERVER,
      IID_ILineCont,
      (void **)&pLineCont);
pLineCont->StartLine((short *)&iLoopIndex);

0
kkandasaAuthor Commented:
Hi,

I tried the follwing and it works !!.
Thanks for pointing me in the right
direction. Please answer so I can
give you the points.

--------
OleInitialize (NULL);
CLSIDFromProgID (L"Plinecont.Plinecontroller", &pClsid)
hrReturnCode = CoCreateInstance (pClsid,
                        NULL,
      CLSCTX_LOCAL_SERVER,
      IID_IDispatch,
        (LPVOID *)&lpDispatch);
hrReturnCode =
lpDispatch->GetIDsOfNames (IID_NULL,
                  &szStartLine,
                        1,
            LOCALE_SYSTEM_DEFAULT,
            &dispid);
dispparams.rgvarg = &myargs[0];
dispparams.rgvarg[0].vt = VT_I2;
dispparams.rgvarg[0].iVal = 1;
dispparams.cArgs = 1;
dispparams.cNamedArgs = 0;

hrReturnCode = lpDispatch->Invoke
(dispid,
IID_NULL,
LOCALE_USER_DEFAULT,
DISPATCH_METHOD,
&dispparams,
NULL,
NULL,
NULL);
--------------
0
Brain2000Commented:
Excellent!  I'm glad you got it working.  ActiveX is a crazy beast.  I've also just recently learned XPCOM, which is a similar, but a simpler model.  Have been writing Mozilla plugins with it.  I also noticed you used a function called CLSIDFromProgID(...).  I figured this function had to exist, and now I know what it is.  That's definately an easier way to get the CLSID than the method I was using.
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C++

From novice to tech pro — start learning today.