Click here to Skip to main content
6,630,586 members and growing! (17,765 online)
Email Password   helpLost your password?
Platforms, Frameworks & Libraries » COM / COM+ » General     Intermediate

Getting the most out of IDispatch

By Xiangyang Liu 刘向阳

A C++ class that makes it extremely easy to use a COM object, even in console apps
VC6Win2K, Visual Studio, COM, Dev
Posted:3 Oct 2001
Updated:11 Dec 2003
Views:366,843
Bookmarked:115 times
Announcements
Loading...
 
Search    
Advanced Search
Add to IE Search
printPrint   add Share
      Discuss Discuss   Broken Article?Report  
347 votes for this article.
Popularity: 10.99 Rating: 4.33 out of 5
6 votes, 5.3%
1
1 vote, 0.9%
2
1 vote, 0.9%
3
6 votes, 5.3%
4
100 votes, 87.7%
5

Introduction

Don't be fooled by the title. Even if you are not (will not be) dealing with the IDispatch interface directly, this article and the included source code could be very useful to you. In my previous article "Buried treasure in MFC: COleDispatchDriver", I introduced XYDispDriver, a class derived from COleDispatchDriver, that can be used to dynamically create and use com objects. The advantage of XYDispDriver is its simple interface. You create and use all (well, almost all) com objects the same way. There is no need for wrapper classes. You don't even need type libraries at compile time.

Then I realized that not all people love MFC as I do. By diving into the source code of COleDispatchDriver, I found out that there is really no need to get MFC involved. I have re-coded the class XYDispDriver from scratch so that it does not depend on any library (sorry, ATL and STL fans :-).

Most of my code is borrowed from MFC, of course. Fortunately, XYDispDriver without MFC is still simple and easy to use.

XYDispDriver

Here are some of the public methods of XYDispDriver. Please note the changes from its previous version.
class XYDispDriver
{
    ...
public:
    XYDispDriver();
    ~XYDispDriver();

    // create a com object with given prog id or class id 

    bool CreateObject(LPCTSTR strProgID, 
       DWORD dwClsContext = CLSCTX_ALL, LPCTSTR
    strServerName = NULL); bool CreateObject(CLSID clsid, DWORD
    dwClsContext = CLSCTX_ALL, LPCTSTR strServerName = NULL);
    // get the type of a property

    VARTYPE GetPropertyType(LPCTSTR strPropertyName);
    // get the property value

    VARIANT* GetProperty(LPCTSTR strPropertyName);
    // set the property value

    bool SetProperty(LPCTSTR strPropertyName, ...);
    // get return type of a method

    VARTYPE GetReturnType(LPCTSTR strMethodName);
    // get number of parameters in a method

    int GetParamCount(LPCTSTR strMethodName);
    // get the type of a parameter in a method

    VARTYPE GetParamType(LPCTSTR strMethodName, const int nParamIndex);
    // invoke a method

    VARIANT* InvokeMethod(LPCTSTR strMethodName, ...);
    // get the last error code as HRESULT

    HRESULT GetLastError() { return m_hRet; }
    // get exception info

    EXCEPINFO* GetExceptionInfo() { return m_pExceptInfo; }
};

The CreateObject functions create a com object: getting a pointer to its IDispatch interface and also querying its ITypeInfo interface to load all the necessary type information. This makes it possible to use the InvokeMethod function to call various com methods in an incredibly flexible way.

The output values of GetProperty and InvokeMethod are stored in internal variables of type VARIANT. These methods will return a pointer to VARIANT or NULL if unsuccessful (for example, the method or property with given name does not exist, or there is a com error). If you don't store the return value, it will be overridden when the same method (or property) is invoked the next time. There is no need to clean up memory for the internal variables. To use XYDispDriver in a multi-threaded process, you can either use a separate object in each different thread or serialize the access to shared objects using critical sections. Please note that the InvokeMethod function can take a variable number of arguments.

For power users, the GetLastError returns the last SCODE and the GetExceptionInfo returns a pointer to an EXCEPINFO structure (maybe NULL if there is no exception).

Sample code

The following code demonstrates how to use XYDispDriver to create a com object and call its methods in a console application.
#include "XYDispDriver.h"

void main()
{
    // declare the dispatch driver

    XYDispDriver disp;
    // create the com object from its prog id

    if(disp.CreateObject("XYDBREADER.XYDBReaderCtrl.1"))
    {
        // call the OpenDB method which takes 3 string arguments and returns 

        // a bool

        VARIANT* pOutput = disp.InvokeMethod("OpenDB","XY_TAG","","");
        if(pOutput&&pOutput->boolVal)
        {
            printf("Database opened\n");
            // call the OpenQuery method which takes a long and a string 

            // arguments and returns a long

            pOutput = disp.InvokeMethod("OpenQuery",0,
              "select * from XYTagName");
            if(pOutput&&pOutput->lVal)
            {
                printf("Query opened: %d\n",pOutput->lVal);
                long nQueryID = pOutput->lVal;
                // call the GetAllRec method which takes a long argument

                // and returns a string (BSTR)

                pOutput = disp.InvokeMethod("GetAllRec",nQueryID);
                if(pOutput)
                {
                    printf("Got data");
                    // print the output data

                    wprintf(L"Returned data:\n%s\n",pOutput->bstrVal);
                    // call the CloseQuery method which takes a long argument

                    // and returns nothing

                    disp.InvokeMethod("CloseQuery",nQueryID);
                }
            }
            // call the CloseDB method which takes no argument and returns

            // nothing

            disp.InvokeMethod("CloseDB");
        }
    }
    printf("done\n");
}

It is also possible to use XYDispDriver with existing com objects. All you need to do is declare an instance of XYDispDriver and call the Attach method (not listed above) passing the IDispatch pointer of the existing com object.

Other Features

You can use XYDispDriver with COM+ to create com object on a remote machine. Here is what you have to do.

  1. Register the com dll or exe on the remote machine. Create a COM+ "Server" application and add this component.
  2. Export the COM+ application from the remote machine (generate a .MSI file).
  3. Import the COM+ application to your local machine (run the .MSI file).
  4. Call the CreateObject method of XYDispDriver passing the name of the remote machine as the third parameter.

The XYDispDriver retrieves type info of a com object it created and uses the type info to call com methods dynamically. Sometimes it is not possible to retrieve type info or not efficient to do so. There is an InvokeVariantMethod method (not listed above) in the XYDispClass class which can be used to invoke almost any com method as long as we have the IDispatch pointer of the com object. To use this method, you need to provide the following.

  1. IDispatch pointer of a com object.
  2. The name of the com method.
  3. Invocation flag (DISPATCH_METHOD, DISPATCH_PROPERTYGET, or DISPATCH_PROPERTYPUT).
  4. Number of parameters for the com method.
  5. List of parameters (the parameter values have to be in VARIANT variables).

Thank you for reading this article, please refer to my home page for other articles and programs.

Recent Updates

  • 12/11/2003 - Modified article text and code to create com object on a remote machine.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Xiangyang Liu 刘向阳


Member

Location: United States United States

Other popular COM / COM+ articles:

Article Top
You must Sign In to use this message board.
FAQ FAQ 
 
Noise Tolerance  Layout  Per page   
 Msgs 1 to 25 of 177 (Total in Forum: 177) (Refresh)FirstPrevNext
Generalcompile error C1010 Pinmembersambugj8:31 23 Jun '09  
GeneralRe: compile error C1010 Pinmembersambugj8:47 23 Jun '09  
GeneralThank you Pinmembero.fofo.o9:23 30 Nov '08  
GeneralNeed some help PinmemberDr.Yak10:05 17 Sep '08  
GeneralRe: Need some help PinmemberJothiMurugeswaran2:58 24 Sep '08  
QuestionMethod returning objects PinmemberDr.Yak14:43 25 Sep '08  
AnswerRe: Method returning objects PinmemberJothiMurugeswaran22:40 25 Sep '08  
GeneralRe: Method returning objects PinmemberDr.Yak11:35 31 Oct '08  
GeneralGood Work Xiangyang Liu PinmemberJothiMurugeswaran2:33 5 Dec '07  
GeneralGiving Access Violation Error ( Debug Mode ) PinmemberJothiMurugeswaran22:57 29 Nov '07  
GeneralUsing special and accented characters PinmemberTDeflers5:40 12 Nov '07  
Generalerror C4430: missing type specifier - int assumed. Note: C++ does not support default-int PinmemberKoundinya5:48 5 Nov '07  
Generalobject which implements interfaces Pinmemberirol3:41 20 Jun '07  
Generalala disphelper Pinmemberbenjamin2316:05 17 Dec '06  
NewsThanks, but don't ignore ATL's CComDispatchDriver Pinmemberkodespace18:03 9 Nov '06  
News"GetProperty" with arguments PinmemberclaudeM7:48 3 Nov '06  
QuestionRe: "GetProperty" with arguments Pinmemberquetzalcoatl_pl6:35 7 Nov '06  
AnswerRe: "GetProperty" with arguments PinmemberclaudeM7:53 22 Nov '06  
QuestionIs there any way to use a property or method of type "VARIANT"? Pinmemberlittle*Prince6:07 22 Aug '06  
GeneralGetTypeAttr failed in LoadTypeInfo PinmemberNagaRam104:19 14 Jul '06  
QuestionSample using existing ocx objext Pinmembercoronys21:04 24 Jun '06  
QuestionEvents ? Pinmembergrideau8:30 16 May '06  
QuestionVT_USERDEFINED issue Pinmemberfdangr6:57 9 May '06  
AnswerRe: VT_USERDEFINED issue PinmemberXiangyang Liu16:26 9 May '06  
AnswerRe: VT_USERDEFINED issue PinmemberclaudeM7:41 3 Nov '06  

General General    News News    Question Question    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

PermaLink | Privacy | Terms of Use
Last Updated: 11 Dec 2003
Editor: Nishant Sivakumar
Copyright 2001 by Xiangyang Liu 刘向阳
Everything else Copyright © CodeProject, 1999-2009
Web19 | Advertise on the Code Project