VB6 变体类型到 .NET 类型
我有一些无法轻易修改的 VB6 代码,如下所示:
Dim cCount as Long
Dim rCount as Long
Dim result()
Set mx = CreateObject("Component.Class")
Dim rtn = mx.GetList(rCount,cCount,result)
它调用的方法当前是一个 VB6 组件,我们已将其迁移到 .NET,但有一个问题。我们不确定 result() 正在寻找什么类型,因为它是一个变体类型。我们尝试过 object、object[]、object[][]、string、string[] 等,但都不起作用。
这是一个示例:
public bool GetList(ref long rCount, ref long cCount, ref object result)
{
...
}
我什至尝试将第三个参数设置为 VariantWrapper,因为它会根据需要添加 ByRef:
public bool GetList(ref long rCount, ref long cCount, VariantWrapper result)
{
...
}
有什么想法可以将传入结果设置为这样,这样我就不会出现未处理的异常吗?
我创建了一个测试接口(针对 COM)、测试类和测试 VB6 应用程序,以确保这是变体的问题。因此,它的定义如下:
.NET 接口:
[DispId(1)]
[ComVisible(true)]
string Test(ref object[] value);
VB 6 方法:
Private Sub Command1_Click()
Set mx = CreateObject("Component.Class")
Dim result()
MsgBox mx.Test(result)
End Sub
与上述相同的问题。在 VB6 中,它简直让我失望。如果我编译并运行它,我会得到一个通用的 .NET 异常并将我抛出。
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 just throws me out. If I compile and run it, I get a generic .NET exception and it throws me out.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
您的 C# 声明是错误的。由于历史原因,VB6“Long”是 32 位。这是 C# 方面的 int。如果堆栈帧错误,您就不可能正确传递“结果”参数。
它应该是一个 SafeArray of Variants,C# 中的 object[]。
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#.
在
mx.GetList(rCount,cCount,result)
行上放置一个断点。点击后,添加mx.GetList(rCount,cCount,result)
的“快速监视”表达式。工具窗口应该向您显示生成的运行时类型是什么。它很可能是一个“comresult”,不会提供太多信息,但它可能会提供返回类型的提示。Put a breakpoint on the
mx.GetList(rCount,cCount,result)
line. Once hit, add a "quick watch" expression ofmx.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.我认为 ref 关键字可能会在这里造成一些麻烦。类型必须完全匹配才能工作。
但是,如果您的方法只是通过值接受对任何
对象
的引用(而不是通过ref
),那么它可以传递任何内容,因为一切都源自 .NET 中的object
。我不知道这对于 VB6/COM 互操作的转化效果如何。但看起来这至少值得一试:
C# 代码:
VB6 代码:
这会给你带来什么吗?
这是一个想法。我在这里可能是完全错误的——我在将 VB6 应用程序迁移到 .NET 方面没有太多经验——但在我看来,如果你能达到这一行(相当于 C#)
……那你就是黄金了。您可以使用反射来确定
GetList
方法需要哪些参数。首先获取代表
mx
类型的System.Type
对象:然后找到该类型的
GetList
方法:这将为您提供包含
GetList
的所有公共重载的MethodInfo[]
数组,采用 3 个参数。从这里开始,结果
的可能类型将是: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 byref
), it can get passed anything, since everything derives fromobject
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:
VB6 code:
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...
...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 ofmx
:Then find the
GetList
method(s) for that type:This will give you a
MethodInfo[]
array of all the public overloads ofGetList
taking 3 parameters. From here the possible types ofresult
will be:我只知道它在 .Net 中的使用方式,其中您传递对
Variant
的引用,如下所示:在此之后,放置一个断点并检查变体类型(如果您不确定)。
最主要的是使用 VariantWrapper 以便 dll 能够理解。
I know only how it's used in .Net where you pass a reference to a
Variant
like this: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.