我不是在谈论从C#调用VBA COM ......反之亦然!
我想要做的是在MS Access中使用VBA调用C#库而不注册DLL。我一直在玩并排互操作一段时间没有成功,我终于想到一个mdb.manifest可能不是exe.manifest的可接受的替代品(可能很明显,我知道,但我我试图保持乐观。
我的问题:是否可以让VBA加载并排的COM组件?
或者,是否有其他方法可以在Access中使用未注册的C#库?
(在你问之前,我的理由是:绝对没有办法让我获得访问我客户端Windows注册表的权限 - 这就是为什么它首先在Access中编写。而且,我需要实现相同的C#应用程序中的功能很快,而不是两次)。
答案 0 :(得分: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的示例。它从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()子。
备注:强>
应该注意的是,该技术的一个限制是,如果.DLL存储在远程网络共享上,它将无法工作。一个简单的解决方案是将其复制到正在使用它的每台PC上的同一本地文件夹中。另一种解决方案是在Access app / VBA项目中包含二进制文件,并让MS-Access导出它们。可以实现的一种方法是将它们存储在Base64中的表格或电子表格中,然后转换它们并将它们导出为二进制文件。
我能够通过创建一个类型库来使用DLL(通过使用tlbexp),并在我的VBA项目中添加对TLB的引用,从而使早期绑定(以及Microsoft IntelliSense)工作,但它确实复杂化有点重要,因为它需要您的VBA应用程序知道DLL和TLB文件的位置(并且还需要有人确保它们在那里)。
答案 1 :(得分:3)
您不必拥有使用SxS的exe,SxS是Activation Context的另一个词。 如果您可以将相关的win32调用导入vba(您可以),则可以使用activation context api加载清单文件。
有关此主题的更多信息,可以找到一些示例here。
答案 2 :(得分:1)
问题是要使用SxS,您需要拥有exe来设置配置以加载SxS程序集。您没有“拥有”Access,虽然您可以放弃正确的配置以使其加载您的.NET COM内容没有注册,但这不是一个“好公民”的举动。
如果你对填充变得棘手,你可以设置一个非托管DLL(或带有dllexport的被攻击的C#类库,例如参见this),并带有一个将加载.NET框架的导出,创建COMVisible DispInterface托管类型的实例并返回它(该方法应返回IDispatch)。然后写一个VBA声明到你的DLL导出函数(声明为返回Object)。如果这没有意义,你可能不应该尝试... :)我之前在类似的情况下做过这个,它确实有效,但我没有一个样本指向你。< / p>
答案 3 :(得分:0)
C#库不是常规DLL。它们更像是在使用之前需要注册的COM库(就像ActiveX控件一样);特别是从非.NET代码调用时。
(当然,除非事情发生了变化......)