与C#和VBA并排COM互操作

tor*_*dal 7 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#应用程序很快,而不是做两次).

tra*_*or1 12

要添加到现有的答案:使用.NET 4.0,在VBA项目中使用C#dll而不注册COM实际上非常简单.

编辑:我刚试过这个,mscorlib.tlb并且mscoree.tlb正在C:\windows\Microsoft.NET\Framework\v2.0.50727加载一个用3.5编译的程序集 - 它运行得很好.显然你不需要.NET 4.0.

以下是如何在VBA项目中使用C#dll的示例.从这个答案略有修改.

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

C:\windows\Microsoft.NET\Framework\v4.0.30319\mscorlib.tlb
C:\windows\Microsoft.NET\Framework\v4.0.30319\mscoree.tlb
Run Code Online (Sandbox Code Playgroud)

(如果您运行的是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");
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

并不需要检查选项"注册为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
Run Code Online (Sandbox Code Playgroud)

4)将DLL复制到Office项目所在的文件夹中,然后在VBA中运行Test()子.

笔记:

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

我能够通过创建一个类型库来使用DLL(通过使用tlbexp),并在我的VBA项目中添加对TLB的引用来获得早期绑定(以及Microsoft IntelliSense),但它确实使事情变得复杂因为它需要您的VBA应用程序知道DLL和TLB文件的位置(并且还需要有人确保它们在那里).


Ale*_*der 3

您不必拥有 exe 即可使用 SxS,SxS 是Activation Context的另一种说法。如果您可以将相关的 win32 调用导入到 vba 中(并且您可以),那么您可以使用激活上下文 api来加载清单文件。

有关该主题的更多信息和一些示例可以在此处找到。