tags:

views:

28

answers:

2

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 PSTORECLib (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.

+2  A: 

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.

Hans Passant
@Hans: Yes, that is where the out paramater I mentioned was missing.
Brian
I don't know what that means.
Hans Passant
@Hans: I was responding to your edit about me omitting the out attribute. My own answer mentioning this issue (using incorrect terminology) was added indicating I figured it out a bit before yours, but in less detail, so I was confirming that you were correct in your understanding of the issue.
Brian
A: 

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.

Brian
Hmm, isn't that what I told you to look for? Why did you mark this as the answer?
Hans Passant
@Hans: I noticed this issue when I was grabbing the IDL to post it, since you'd asked me to do so. Since this caused me to notice the problem, I also upvoted you. You did edit your post to mention the possibility of omitting the out attribute, but you did so after I wrote this answer (about an hour later, IIRC).
Brian
Hmya, this is very common, somebody asking the right question and setting the solution in motion. The skill is in asking that right question of course. Never saw your post, there is no notification for that and the comment was too mysterious. Pissing off a contributor is entirely your prerogative, please remind me when I accidentally try to help you again. "Brian" is a bit hard to filter.
Hans Passant