开发者

VB6 Variant Type to .NET Type

开发者 https://www.devze.com 2023-01-07 05:14 出处:网络
I have some VB6 code that can\'t be modified easily that looks like this: Dim cCount as Long Dim rCount as Long

I have some VB6 code that can't be modified easily that looks like this:

Dim cCount as Long
Dim rCount as Long
Dim result()

Set mx = CreateObject("Component.Class")
Dim rtn = mx.GetList(rCount,cCount,result)

The method it calls is currently a VB6 component that we've migrated to .NET with one issue. We're not sure what type the result() is looking for since it's a variant type. We've tried object, object[], object[][], string, string[], etc, none of which have worked.

Here's an example:

public bool GetList(ref long rCount, ref long cCount, ref object result)
{
  ...
}

I've even tried setting the third param to VariantWrapper since it will add ByRef as necessary:

public bool GetList(ref long rCount, ref long cCount, VariantWrapper result)
{
  ...
}

Any ideas what I can set the incoming result to be so that I don't have an unhandled exception?

I've created a test Interface (for COM), test Class, and test VB6 app to ensure it was an issue with the Variant. So, it's defined like so:

.NET Interface:

[DispId(1)]
[ComVisible(true)]
string Test(ref object[] value);

VB 6 method:

Private Sub Command1_Click()
    Set mx = CreateObject("Component.Class")
    Dim result()
    MsgBox mx.Test(result)
End Sub

Same issue as described above. In VB6, it j开发者_运维技巧ust throws me out. If I compile and run it, I get a generic .NET exception and it throws me out.


Your C# declaration is wrong. A VB6 "Long" is 32-bits for historical reasons. That's an int on the C# side. With the stack frame wrong, you have no odds of getting the "result" argument passed correctly.

It ought to be a SafeArray of Variants, object[] in C#.


Put a breakpoint on the mx.GetList(rCount,cCount,result) line. Once hit, add a "quick watch" expression of mx.GetList(rCount,cCount,result). The toolwindow should show you what the resulting runtime-type is. Most likely it is a "comresult" and will not provide much information, but it may provide a hint to the return type.


I think the ref keyword may be causing some trouble here. The types have to match exactly for that to work.

However, if your method simply accepts a reference to any object by value, (instead of by ref), it can get passed anything, since everything derives from object in .NET.

How well this translates to VB6/COM interop, I don't know. But it seems that this is at least worth a shot:

C# code:

public string GetTypeName(object value)
{
    return value.GetType().FullName;
}

VB6 code:

Set mx = CreateObject("Component.Class")
Dim result()

MsgBox mx.GetTypeName(result)

Does that give you anything?


Here's an idea. I could be dead wrong here -- I've not much experience in migrating VB6 apps to .NET -- but it seems to me that if you can get as far as (the C# equivalent of) this line...

Set mx = CreateObject("Component.Class")

...then you're golden. You can use reflection to figure out what parameters the GetList method wants.

First get the System.Type object representing the type of mx:

Type mxType = mx.GetType();

Then find the GetList method(s) for that type:

MethodInfo[] getListMethods = mxType.GetMember("GetList")
    .OfType<MethodInfo>()
    .Where(m => m.GetParameters().Length == 3)
    .ToArray();

This will give you a MethodInfo[] array of all the public overloads of GetList taking 3 parameters. From here the possible types of result will be:

Type[] possibleResultTypes = getListMethods
    .Select(m => m.GetParameters()[2].ParameterType)
    .ToArray();


I know only how it's used in .Net where you pass a reference to a Variant like this:

 int port = 2;
 object pvPort = new System.Runtime.InteropServices.VariantWrapper(port);
 gimp.SetPort(ref pvPort);

After this, put a breakpoint and check the variant type if you're not sure about it.

The main thing is using VariantWrapper so the dll understands.

0

精彩评论

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