Enumeration of method and property names of COM objects in. Net

Source: Internet
Author: User
Tags error handling function prototype functions header requires tostring
Method and property names of objects that enumerate COM objects in. Net

Author:zee

Well, I used to ask this question, no one said, or do it yourself better.

Generally, when a COM object is provided, it usually provides a type library in which all the method names, parameter names, property names, and so on of the COM object are defined. All we have to do is take this information out of the type library.
Of course, some COM objects that are used only by C + + programmers do not have type libraries, instead of C + + header files and/or IDL files, in this case, there is generally no way in the program to enumerate the object's method attributes: After all, to find C + + header file is not realistic, not to mention in the development environment, there is no header file said.
Therefore, we will discuss the problem of enumerating method/property names when COM objects exist typelib.
Locating from COM objects to typelib
In general, the TypeLib information for a COM object is stored in the registry: Under the Hk_classroot\clsid\{classid}\ registry key, there is a subkey named TypeLib that defines the ID of the COM object type library; Classroot\typelib the registry key, enumerates all the TypeLib in the system.
Look at what we're going to do first: Get ClassID from ProgID, which can be done by invoking the CLSIDFromProgID function of the COM base library, which is defined in the Platform SDK as follows:
HRESULT CLSIDFromProgID (
LPCOLESTR Lpszprogid ,
Lpclsid pCLSID

);
In order to be in. NET, we use the DllImport attribute to introduce this function into. NET:
Class unsafenativemethods{
[DllImport ("Ole32.dll", Charset=charset.unicode,preservesig=false)]
public static extern void CLSIDFromProgID ([In,marshalas (UNMANAGEDTYPE.BSTR)] string lpszprogid,[out]out Guid pclsid);
.........
We can then call this function in. Net to get ClassID:
Guid clsid;
Unsafenativemethods.clsidfromprogid (Progid,out clsid);
OK, upgrade the Treasure Class ID start, Level up! Strength + 3, LIFE + 5, must kill technology DLL import acquisition. : Next task: Get typelib.
L Obtain typelib.
Provides access to typelib,com with two interfaces: ITypeLib and ITypeInfo, where ITypeLib provides access to TypeLib, while ITypeInfo represents an item TypeLib defined in ITypeInfo.
To get itypeinfo,com There are two functions that can do this: LoadTypeLib and Loadregtypelib. Where loadtypelib requires the path of the TypeLib file as a parameter, and Loadregtypelib obtains TypeLib based on the TypeLib ID of TypeLib and the version number of ITypeLib. Here, we use Loadregtypelib to get the ITypeLib interface.
First, prepare the required parameters: The version number of TypeLibId and typelib, which needs to be obtained from the registry:
RegistryKey RegKey = registry.classesroot;
RegKey = Regkey.opensubkey ("clsid\\{" + CLSID). ToString () + "}\\typelib");
GUID typelibid = new GUID (Regkey.getvalue (""). ToString ());
Get TypeLib versions
Short Imajorver,iminusver;
RegKey = Microsoft.Win32.Registry.ClassesRoot;
RegKey = Regkey.opensubkey ("typelib\\{" + typelibid.tostring () + "}");
string[] arytemp = Regkey.getsubkeynames ();
String sversion = Arytemp[0];
Arytemp = Sversion.split ('. ');
Imajorver = short. Parse (Arytemp[0],system.globalization.numberstyles.allowhexspecifier);
Iminusver = short. Parse (arytemp[1], System.Globalization.NumberStyles.AllowHexSpecifier);
One thing to note here: The typelib version number in the registry is in hexadecimal format, and if you're lucky, you'll find a version number like "1.a", so we'd better think of it as a 16-binary conversion.
Now you can call Loadregtypelib, and like CLSIDFromProgID, import it in first:
This is the Loadregtypelib function prototype:
Rguid ,             
Wvermajor ,  
Wverminor ,  
LCID ,                 
Pptlib

);
Well, in. NET, this function looks like this:
[DllImport ("Oleaut32.dll", Charset=charset.unicode,preservesig=false)]
[Lcidconversion (3)]
public static extern ucomitypelib Loadregtypelib (ref Guid Rguid, [In,marshalas (UNMANAGEDTYPE.U2)]short wvermajor, MarshalAs (UNMANAGEDTYPE.U2)]short Wverminor);
Ah, a little trick: in the definition of. Net, I do not define the parameter of the LCID in the prototype, because I applied the lcidconversionattribute, which means that this method requires an LCID to do the parameter, the position of the parameter: [ Lcidconversion (3)]--the third parameter. This way, when this method is invoked, the. Net marshaler automatically provides the LCID parameter. Nice to put:)
In addition, in the System.Runtime.InteropServices namespace of the. NET Framwork, some of the. NET managed definitions of common COM interface are defined, although not much, but fortunately we are going to use the ITypeLib and ITypeInfo these two interfaces, which are System.Runtime.InteropService. UcomitypelibAnd System.Runtime.InteropService. Ucomitypeinfo。 This saves us the task of defining our own interfaces.
Well, the next thing is easy:
Ucomitypelib TypeLib;
TypeLib = Unsafenativemethods.loadregtypelib (ref typelibid,imajorver,iminusver);
Bingo! Mission complete! Just one last task: Navigate to the ITypeInfo of our COM object and extract the information we need from it.
The Getitypeinfo method of the ITypeInfo interface together with the Getitypeinfocount method provides the ability to traverse all itypeinfo in the typelib, but since we have the classid of COM objects on our hands, The ITypeInfo of COM objects can be obtained by using the Getitypeinfoofguid method.
Ucomitypeinfo ITypeInfo;
Typelib.getitypeinfoofguid (ref clsid,out ITypeInfo);
After getting the ITypeInfo, first we need to see how many methods/attributes there are in this itypeinfo, which requires us to call its Gettypeattr method to get the TYPEATTR structure.
Typeattr typeattr;
IntPtr p_typeattr = IntPtr.Zero;
Itypeinfo.gettypeattr (out p_typeattr);
Typeattr = (typeattr) marshal.ptrtostructure (p_typeattr,typeof (typeattr));
Getting the TYPEATTR structure is a little bit of a hassle, because. NET typeattr that do not support unmanaged signatures **parameter, the gettypeattr is defined only by using the reference INTPTR parameter. Then we need to marshal the data from the unmanaged memory block to the managed object with Marshal.PtrToStructure. In the TYPEATTR structure, the Cfuns field represents the number of functions described by the current trpeinfo, and the description of each function is described by the GETFUNCDESC structure obtained by the ITypeInfo Funcdesc method.
if (Typeattr.cfuncs > 0)
{
for (int i=0;i<typeattr.cfuncs;++i)
{
Get Funcdesc struct
Funcdesc Funcdesc;
IntPtr P_funcdesc;
Itypeinfo.getfuncdesc (I,out P_funcdesc);
Funcdesc = (FUNCDESC) marshal.ptrtostructure (p_funcdesc,typeof (FUNCDESC));
......
Like Typeattr, the FUNCDESC structure also needs marshal.ptrtostructure to deal with, I will not say more.
The nasty is: FUNCDESC structure does not have the name of the function, we can only through its Memid fields and Invkind fields to know the function of the member ID and the type of function. The type of function is what we need: It tells us that this function is a method or a Get/set method of a property, and the name of this thing, we have to turn to the Itypeinfo:getnames method gets the member name with the specified member ID, which returns a string array, For methods, the first element of the array is the method name, followed by the method's parameter name, and the property name appears in the first element of the array for the property.
Okay, now, except for one thing, I've already said that, and we already know how to get the name of the method/attribute from ITypeInfo, and how to set up two empty collection to store the method and property names, respectively. How to traverse all the funcdesc of ITypeInfo and insert elements into the corresponding collection according to each function type I don't want to say more. The only problem we have left is: for all the COM objects generated by VB, follow the steps above to walk down, we do not see any method properties.
Why, with OLEView look at these DLLs typelib understand: VB will generate a class name "_" + Class name interface, this interface inherits from IDispatch, all method attributes are defined on this interface, and implementation class is simply to implement this interface, In its typelib, there are no members in the implementation class that really corresponds to ClassID.
Now that we know why, there is a way: when we enumerate all the methods/properties of a COM object, we should not enumerate only the typeinfo that correspond to its own classid, and the methods/attributes defined in all other interfaces of the TypeInfo inheritance should be taken out as well. And to navigate to the other interfaces it inherits, we're going to do exactly the same thing as all the funcdesc that traverse this itypeinfo:
if (Typeattr.cimpltypes > 0)
{
for (int i=0;i<typeattr.cimpltypes;++i)
{
int href;
Ucomitypeinfo Imptypeinfo;
TypeInfo. Getreftypeofimpltype (i,out href);
TypeInfo. Getreftypeinfo (Href,out imptypeinfo);
Now we can does the same thing to the imptypeinfo like TypeInfo
......
}
}

The Typeattr cimpltypes field represents the number of interfaces that the ITypeInfo implements, and the ITypeInfo Getreftypeofimpltype method obtains a reference to a handle to an implemented interface, and Getreftypeinfo Method gets the ITypeInfo of the interface from the reference of this handle. Obviously, we can write a recursive function to walk through the interfaces of all COM object implementations, and we can be sure that the recursion is exportable: because all the interfaces in COM are ultimately derived from the "I don't Know" interface. ^-^
Finally, I think in most cases, you don't want to see QueryInterface or AddRef such IUnknown interfaces in the COM object's list of methods, and IDispatch interfaces that are like invoke. There are not many people who want to be interested, But anyway, the bottom method is just a few, and when you traverse it can be judged to filter out the names of these methods.

Disclaimer Statement:
In this article, for clarity, there is no error handling in all the given code. If you use some of the code in this article in your code, I am not responsible for any consequences such as program errors, system downtime, walking trees, cell phone explosions, flood levees, earth destruction, and so on.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.