开发者

Cleaner way to code instead of Marshall.QueryInterface?

I am wondering if there is a cleaner way to write the (working) code below:

uint uEnum = 0;
PStore.EnumTypes(0, 0, ref uEnum);
System.Reflection.MemberInfo inf = typeof(PSTORECLib.CEnumTypes);
GuidAttribute CEnumGuid = 
    (GuidAttribute)inf.GetCustomAttributes(typeof(GuidAttribute), false)[0];
Guid tmp = new Guid(CEnumGuid.Value);
IntPtr ppv;
Marshal.QueryInterface((IntPtr)uEnum, ref tmp, out ppv);
PSTORECLib.CEnumTypes EnumPStoreTypes = 
    (PSTORECLib.CEnumTypes)Marshal.GetObjectForIUnknown(ppv);

//Later
Marshal.Release(ppv);

When I tried stuffing IEnumPStoreTypes** in the idl file of the PSTORE开发者_开发知识库CLib (i.e. when I used the initial IDL output by oleview) into the call to PStore.EnumTypes, the dll output by tlbimp told me to pass in a reference to a CEnumTypes. The function was happy with this (it returned S_OK), but it didn't populate the reference. This mess of ugly code is what happened when I changed it to accept a pointer to a long instead, and is what I did to get an instance of CEnumTypes to refer to the pointer. This whole thing strikes me as being a bit messy, though it does work. Is there a cleaner way to do this?

Note that the line PSTORECLib.CEnumTypes cen = new PSTORECLib.CEnumTypes(); will throw a "Class Not Registered" COMException.


Ouch, you're hacking COM the low-level way. It is roughly okay, but there are problems. It will never work in 64-bit mode, uEnum can't be a uint, it has to be a pointer. It is also being leaked, you don't call Release() for it. You can't ignore that.

Clearly you've got a type library and created a interop library from it or else the reflection code wouldn't work. I can only guess that there's something wrong with the IDL. The signature of EnumTypes suggests that you forgot the [out,retval] attributes on the last argument. At least post the IDL for EnumTypes.


I started to edit my post to provide the information Hans Passant asked for, then I had an epiphany and figured out the problem. For some reason, both the old version of the typelibrary created by a previous person working on this project and mine had a similar issue, likely because both of us trusted oleview more than we should have.

In particular, one of the parameters was an [in] parameter instead of an [out] parameter. VB6 didn't care, but C# cared a lot.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜