views:

36

answers:

3

I'm having trouble with a COM library I'm trying to use. I get an ArgumentException when I call a particular method and pass it null. This happens to me in both a C# project and a VB.NET project (I call the method using Nothing) where I added the library reference from the "COM" list in Visual Studio 2008. When I call this same method in Python, passing in None, the method works as expected with no errors. It's my understanding that Python interacts with the COM library through DCOM (and I have only the fuzziest notion what that means) whereas I might be using the COM library directly when I reference it in my C#/VB.NET projects. Could something be happening that would cause the parameter I pass to get screwed up before it gets to the COM library? I'm not sure what's happening here. I recently updated the COM library to a newer version, so I wondered if perhaps I was getting version conflicts in there somewhere, causing the exception. I removed all references to the COM library from my C# and VB.NET projects, deleted all bin and obj directories, and re-added the reference. This did cause the Interop.MyCOMLibrary.dll file that shows up in obj to have today's date instead of the older date I had been seeing.

The only documentation I have for the COM library describes the method as follows:

Public Function AddItem( _
   ByVal ItemData As Variant _
) As Object

I'm trying to search around for issues regarding Variant parameters now.

Edit: so while Type.Missing and the other solutions work for getting me past that method call without error, trying to read certain string properties on the returned item from that method result in:

System.Runtime.InteropServices.COMException: Item does not exist.

This is another example where it worked in Python but is throwing an exception in C#, so I'm guessing more DCOM-versus-COM weirdness. Or perhaps this is a threading issue, since I'm using MSTest to test.

+2  A: 

Did you try using Reflection.Missing instead of Nothing/null?

Richard Hein
I tried `AddItem(default(System.Reflection.Missing))` just now and got the same ArgumentException as usual. I'm not sure how you meant to use `Missing`, so I just tried `default()`.
Sarah Vessels
@Sarah Try `System.Reflection.Missing.Value`
Henk Holterman
@Sarah, @Henk: Yeah, like he said, use Missing.Value.
Richard Hein
Looks like that works! Hans suggested `Type.Missing`, which works, and I discovered `new object()` works. I think `Type.Missing` sounds preferable since I try not to use `Reflection` stuff unless necessary. I don't know if there's actually any difference in the two, though.
Sarah Vessels
@Sarah: System.Type.Missing is actually set equal to System.Reflection.Missing.Value in Type's static constructor. I think Type.Missing was added after .NET 1.0 sometime, but I'm not sure. I know that System.Reflection.Missing.Value was the way I used to have to do it for all optional parameters. Type.Missing is shorter, so I'd use that now.
Richard Hein
+2  A: 

Yes, null is not likely to be correct. There are a couple of Variants that indicate "no data", like VT_EMPTY, VT_ERROR, VT_NULL. Start by passing Type.Missing.

Hans Passant
Looks like `Type.Missing` works! I posted an answer about how passing `new object()` also works, but I'm guessing `Type.Missing` would be preferable here since it sounds closer to the original `null` I wanted to pass.
Sarah Vessels
+1  A: 

I read in this article about going from VB to VB.NET and it said to use object in .NET since Variant doesn't exist. I had previously tried passing default(object), which didn't work, but I tried passing new object() as the parameter and that worked--no exception was thrown! What I don't understand is why an instance of an object has to be passed when that's supposed to be an optional parameter. Why does null not get translated somehow to new object()?

Typing up this question on StackOverflow is what led me to this answer after two days of puzzling over it, because I had to copy/paste the exact method description from documentation. That's when I noticed Variant instead of Object for the parameter. :)

Sarah Vessels