这似乎很容易在这里找到,但如果之前有人问过,我就不知道在哪里。
基本上,我是一名.NET开发人员,我不得不使用VB6一分钟,并学习制作COM DLL。我正在使用C#工作,我正在尝试使用该语言创建一个COM DLL,以便将自定义类/结构返回到某些VB6代码,尽管答案here很容易在返回{时使用{来自COM方法的{1}}或string
,我无法使用实际对象。
示例代码:
C#
int
VB6
using System;
using System.Runtime.InteropServices;
namespace One.Two.Three
{
[Guid("<some GUID>"), ClassInterface(ClassInterfaceType.None)]
public class SomeClass : ISomeClass
{
public string Test1 { get; set; } = "Tesuto Ichiban";
public string Test2 { get; set; } = "Tesuto Niban";
public SomeClass SomeFunction(ref string str1, ref string str2, ref string str3,
ref bool someBool, string str4)
{
return new SomeClass();
}
}
[Guid("<another GUID>")]
public interface ISomeClass
{
SomeClass SomeFunction(ref string str1, ref string str2, ref string str3, ref bool
someBool, string str4);
}
public class Test
{
public string Test1 { get; set; } = "Tesuto Ichiban";
public string Test2 { get; set; } = "Tesuto Niban";
}
}
当返回值为 MsgBox ("start")
Dim result As Object
Dim someObj
Set someObj = CreateObject("One.Two.Three.SomeClass")
result = CallByName(someObj, "SomeFunction", VbMethod, "1", "2", "3", True, "4")
MsgBox (result)
'MsgBox (result.toString())
'MsgBox (result.Test1)
'MsgBox (result.Test2)
MsgBox ("end")
或string
时(以及int
被声明为result
时),此方法效果很好,此时值可以被传递到String
并向用户显示就好了。但是,如果返回 MsgBox
或 SomeClass
,那么任何将Test
传递给result.[toString()/Test1/Test2]
的尝试都会产生消息&#34;开始&#34;和&#34;结束&#34;仍然正在向用户显示,但两者之间根本没有任何显示(甚至不是空白消息)。
值得注意的是,通过返回MsgBox
的实例并将Test
声明为result
,对String
的调用将显示&#34; One.Two .Three.Test&#34; - 这表明那里发生了一些事情。
所以......问题是:
还需要做些什么来使VB6应用程序能够公平地访问此对象?
特别是,我需要返回一个数组,MsgBox (result)
或某些对象,每个对象都有几个成员。再一次,这似乎是相对容易在Google或SO上找到的东西,但它似乎被其他搜索结果所掩盖。
P.S。 dll的.NET Framework是4.5。 (我在4.0文件夹中使用了RegAsm,而不是链接答案中特别提到的2.0)。如果需要降低到4.0,我可能会,但可能无法将其一直降到2.0。
答案 0 :(得分:3)
不仅有一种方法可以使这项工作,但这里有一个简单的方法,与您的工作方式相匹配:
C#代码可以非常简单,您不需要明确声明接口,不需要在任何地方使用Dim result As Object
Dim someObj
Set someObj = CreateObject("One.Two.Three.SomeClass")
' note the "Set" keyword, it's mandatory for COM objects...
Set result = CallByName(someObj, "SomeFunction", VbMethod, "hello world")
MsgBox result.Text
关键字等,但是您做需要在您的类中添加// progid is now optional because we won't need CreateObject anymore
[ProgId("One.Two.Three.SomeClass")]
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeClass1
{
public SomeClass2 SomeFunction(string text)
{
return new SomeClass2 { Text = text };
}
}
[ComVisible(true)]
[ClassInterface(ClassInterfaceType.AutoDual)]
public class SomeClass2
{
public string Text { get; set; }
}
属性(字符串,整数等等是隐含的ComVisible):
ClassInterfaceType.AutoDual
VB / VBA代码:
Dim c1 As New SomeClass1
Set c2 = c1.SomeFunction("hello world")
MsgBox c2.Text
但是,如果你想从VB / VBA获得Intellisense,你也可以声明这样的类:
ClassInterfaceType.AutoDual
我刚刚添加List<T>
,现在我可以引用TLB(我使用regasm / tlb创建),并在VB / VBA中使用此代码:
theValue
thValue
不推荐&#34;&#34;因为如果你走这条路线,你必须确保COM客户端(这里是VB / VBA)和COM服务器(这里是C#)之间的二进制文件是100%同步的,否则你可能会遇到很难的VB / VBA崩溃。然而,它是一种妥协,智能感知是一种伟大的生产力工具恕我直言。
关于返回thValue
的最后一句话,你会遇到麻烦。如果你面对它,请问另一个问题: - )