c# - 与 C# 和 VBA 的并行 COM 互操作

标签 c# vba com-interop side-by-side

我不是在谈论从 C# 调用 VBA COM...相反!

我想做的是在 MS Access 中使用 VBA 调用 C# 库而不注册 DLL。我一直在玩并排互操作一段时间但没有成功,我终于想到 mdb.manifest 可能不是 exe.manifest 的可接受替代品(可能很明显,我知道,但我试图保持乐观)。

我的问题:是否可以让 VBA 加载并排 COM 组件?

或者,还有其他方法可以在 Access 中使用未注册的 C# 库吗?

(在你问之前,我的理由是:我绝对不可能被授予访问我客户的 Windows 注册表的权限——这就是为什么它首先是用 Access 编写的。而且,我将需要实现相同的C# 应用程序中的功能很快,而不是两次)。

最佳答案

要添加到已经存在的答案中:使用 .NET 4.0,在不注册 COM 的情况下在 VBA 项目中使用 C# dll 实际上非常简单。

编辑:我刚刚用 C:\windows\中的 mscorlib.tlbmscoree.tlb 尝试了这个Microsoft.NET\Framework\v2.0.50727——加载在 3.5 中编译的程序集——它工作得很好。显然您不需要 .NET 4.0。

以下是如何在 VBA 项目中使用 C# dll 的示例。它由 this 稍作修改回答。

1) 添加对以下类型库的引用您的 VBA 项目(工具 -> 引用):

C:\windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb
C:\windows\Microsoft.NET\Framework\v4.0.30319\mscoree.tlb

(如果您运行的是 64 位 Office,请使用 Framework64 文件夹)

2) 在您的 C# 项目中,确保将 [ComVisible(true)] 属性添加到您的类中:

using System.Windows.Forms;
using System.Runtime.InteropServices;
namespace VB6FuncLib
{
    [ComVisible(true)]
    public class VB6FuncLib
    {
        public VB6FuncLib()
        { }
        public void test()
        {
            MessageBox.Show("Test Successful");
        }
    }
}

不需要选中“为 COM Interop 注册”选项。这仅用于构建标准 COM 对象。您也不必选中“使程序集 COM 可见”,除非您希望整个程序集可见(这也将消除对 COMVisible 属性的需要)。

3) 在您的 VBA 代码中,使用以下代码添加一个新模块:

Sub Test()
    Dim Host As mscoree.CorRuntimeHost
    Set Host = New CorRuntimeHost
    Host.Start
    Dim Unk As IUnknown
    Host.GetDefaultDomain Unk
    Dim AppDomain As AppDomain
    Set AppDomain = Unk
    Dim ObjHandle As ObjectHandle
    Set FS = CreateObject("Scripting.FileSystemObject")
    Path = FS.GetParentFolderName(CurrentDb().Name)
    Set ObjHandle = AppDomain.CreateInstanceFrom(Path & "\VB6 Function Library.dll", "VB6FuncLib.VB6FuncLib")
    Dim ObjInstance As Object
    Set ObjInstance = ObjHandle.Unwrap
    ObjInstance.test
    Host.Stop
End Sub

4) 将 DLL 复制到与 Office 项目相同的文件夹中,然后在 VBA 中运行 Test() sub。

注意事项:

应该注意的是,这种技术的局限性之一是如果 .DLL 存储在远程网络共享上,它就无法工作。一个简单的解决方案是将它复制到每台使用它的 PC 上的同一个本地文件夹中。另一种解决方案是将二进制文件包含在您的 Access 应用程序/VBA 项目中,并让 MS-Access 导出它们。一种可以实现的方法是将它们以 Base64 格式存储在表格或电子表格中,然后转换它们并将它们导出为二进制文件。

我能够通过创建一个与 DLL 一起使用的类型库(通过使用 tlbexp)并在我的 VBA 项目中添加对 TLB 的引用,使早期绑定(bind)(以及 Microsoft IntelliSense)工作,但这确实很复杂有点重要,因为它需要您的 VBA 应用程序知道 DLL 和 TLB 文件在哪里(并且还需要有人确保它们在那里)。

关于c# - 与 C# 和 VBA 的并行 COM 互操作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1903220/

相关文章:

c# - 创建动态 SQL DbParameter 值

c# - CsvHelper : Adding a title using CsvHelper

c# - 我应该总是调用 Page.IsValid 吗?

vba - DoCmd.Transfertext - 如何修改规范?

vba - Excel VBA 浏览工作表并将列范围复制到另一个工作表

c# - 在 C# 中访问 VB6 字符串的最快方法

C# 相当于 AS3 Vector?

vba - 如何在 VBA 中更改打印机对话框的默认名称? (使用打印机对话框的句柄时)

com - 如何使用 COM 公开 .netstandard2.0 库以在 VB6 中使用?

c# - 是否可以使用 com interop 将变体数组传递给 C#?