Getting the most out of IDispatch(XYDispDriver)
2011-09-27 11:37
453 查看
Introduction
Don't be fooled by the title. Even if you are not (will not be) dealing with theIDispatchinterface 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
XYDispDriveris 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
XYDispDriverfrom 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,
XYDispDriverwithout MFC is still simple and easy to use.
XYDispDriver
Here are some of the public methods ofXYDispDriver. Please note the changes from its previous version.
Collapse |
Copy Code
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
CreateObjectfunctions create a
com object: getting a pointer to its
IDispatchinterface and also querying its
ITypeInfointerface to load all the necessary type information. This makes it possible to use the
InvokeMethodfunction to call various
com methods in an incredibly flexible way.
The output values of
GetPropertyand
InvokeMethodare stored in internal variables of type
VARIANT. These methods will return a pointer to
VARIANTor
NULLif 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
XYDispDriverin 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
InvokeMethodfunction can take a variable number of arguments.
For power users, the
GetLastErrorreturns the last
SCODEand the
GetExceptionInforeturns a pointer to an
EXCEPINFOstructure (maybe
NULLif there is no exception).
Sample code
The following code demonstrates how to useXYDispDriverto create a
com object and call its methods in a console application.
Collapse |
Copy Code
#include "XYDispDriver.h" void main() { // declare the dispatch driver XYDispDriverdisp; // 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
XYDispDriverwith existing
com objects. All you need to do is declare an instance of
XYDispDriverand call the
Attachmethod (not listed above) passing the
IDispatchpointer of the existing com object.
Other Features
You can useXYDispDriverwith COM+ to create
com object on a remote machine. Here is what you have to do.
Register the com dll or exe on the remote machine. Create a
COM+ "Server" application and add this
component.
Export the COM+ application from the remote machine (generate a .MSI file).
Import the COM+ application to your local machine (run the .MSI file).
Call the
CreateObjectmethod of
XYDispDriverpassing the name of the remote machine as the third parameter.
The
XYDispDriverretrieves 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
InvokeVariantMethodmethod (not listed above) in the
XYDispClassclass which can be used to invoke almost any
com method as long as we have the
IDispatchpointer of the
com object. To use this method, you need to provide the following.
IDispatchpointer of a com object.
The name of the com method.
Invocation flag (
DISPATCH_METHOD,
DISPATCH_PROPERTYGET, or
DISPATCH_PROPERTYPUT).
Number of parameters for the com method.
List of parameters (the parameter values have to be in
VARIANTvariables).
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 createcom 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
相关文章推荐
- Getting the most out of your pixels - adapting to view state changes(WIN8下设计适应多种分辨率的APP)[转.原]
- 3 Getting the Most Out of Everyday Tools
- a very good guide to makethe Most Out of the SQL Server 2005 Performance Dashboard
- Hacking Vim: A Cookbook to get the Most out of the Latest Vim Editor
- Tweaking your system to get the most out of BitTorrent
- Photoshop CS2 RAW : Using Adobe Camera Raw, Bridge, and Photoshop to Get the Most out of Your Digita
- csharp: using OleDb Getting the identity of the most recently added record
- csharp: using OleDb Getting the identity of the most recently added record
- csharp: using OleDb Getting the identity of the most recently added record
- Seven effective ways to get the most out of the morning
- Ready to make the most of out of your amazing iPad?
- Figure out which databases involve most of the I/O
- 解决eclipse中出现Resource is out of sync with the file system问题
- zeromq samples getting the message out
- “Resource is out of sync with the file system”问题
- 解决eclipse中出现Resource is out of sync with the file system问题
- Myeclipse:resource is out of sync with the file system的解决办法
- 修复Eclipse "resource is out of sync with the file system"
- Could not find output/file.out in any of the configured local directories
- Lesson33 Out of the darkness