gpt4 book ai didi

c# - 如何将结构或类从 .NET COM dll 返回到使用的 VB6 应用程序?

转载 作者:行者123 更新时间:2023-11-30 15:57:36 26 4
gpt4 key购买 nike

这似乎很容易在这里找到,但如果以前有人问过,我不知道在哪里。

基本上,我是一名 .NET 开发人员,必须花一分钟时间使用 VB6 并学习如何制作 COM DLL。我在 C# 中工作,并试图获得用该语言制作的 COM DLL,以将自定义类/结构返回给某些 VB6 代码,尽管答案是 here返回 string 时很容易使用或 int从 COM 方法,我无法让它与实际对象一起工作。

示例代码:

C#

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";
}
}

VB6

  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] 的尝试至 MsgBox结果消息“开始”和“结束”仍然很好地显示给用户,但中间什么也没有显示(甚至没有空白消息)。

值得注意的是,通过返回 Test 的一个实例离开result声明为 String , 调用 MsgBox (result)将显示“One.Two.Three.Test”——这表明那里正在发生某些事情。

那么……问题是:

还需要做些什么才能让 VB6 应用程序公平地访问此对象?

特别是,我需要返回一个数组,List<T> ,或某些对象的某些内容,每个对象都有多个成员。同样,这似乎应该在 Google 或 SO 上相对容易找到,但它似乎被其他搜索结果淹没了。

附言dll 的 .NET Framework 是 4.5。 (我使用了 4.0 文件夹中的 RegAsm,而不是链接答案中特别提到的 2.0)。如果需要将其降低到 4.0,我可能可以,但可能无法一直降低到 2.0。

最佳答案

不仅有一种方法可以使这项工作有效,而且这里有一种与您的工作方式相匹配的简单方法:

C#代码可以很简单,你不需要显式声明接口(interface),你不需要使用ref到处都是关键字等等,但是您确实需要添加 ComVisible(true)类的属性(字符串、整数等隐式 ComVisible):

[ComVisible(true)]
[ProgId("One.Two.Three.SomeClass")]
public class SomeClass1
{
public SomeClass2 SomeFunction(string text)
{
return new SomeClass2 { Text = text };
}
}

[ComVisible(true)]
public class SomeClass2
{
public string Text { get; set; }
}

VB/VBA代码:

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

但是,如果你想从 VB/VBA 获得智能感知,你也可以像这样声明类:

// 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; }
}

我刚刚添加了 ClassInterfaceType.AutoDual ,现在我可以引用一个 TLB(我使用 regasm/tlb 创建),并在 VB/VBA 中使用此代码:

Dim c1 As New SomeClass1
Set c2 = c1.SomeFunction("hello world")
MsgBox c2.Text

ClassInterfaceType.AutoDual不是“推荐”的,因为如果你走那条路,你必须确保 COM 客户端(这里是 VB/VBA)和 COM 服务器(这里是 C#)之间的二进制文件是 100% 同步的,否则你可能会遇到困难的 VB/VBA 崩溃。然而,这是一种折衷,intellisense 是一个很棒的生产力工具恕我直言。

关于返回的最后一句话 List<T> ,你会遇到麻烦。如果你面对它,再问一个问题:-)

关于c# - 如何将结构或类从 .NET COM dll 返回到使用的 VB6 应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44729388/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com