[英]Side-By-Side COM Interop with C# and VBA
我不是在談論從C#調用VBA COM ......反過來說!
我想要做的是在MS Access中使用VBA調用C#庫而不注冊DLL。 我一直在玩並排互操作一段時間沒有成功,我終於想到一個mdb.manifest可能不是exe.manifest的可接受的替代品(可能很明顯,我知道,但我我試圖保持樂觀。
我的問題:是否有可能讓VBA加載並排的COM組件?
或者,是否有另一種方法在Access中使用未注冊的C#庫?
(在您提出問題之前,我的理由是:我絕對無法訪問我的客戶端的Windows注冊表 - 這就是為什么它首先在Access中編寫。而且,我需要在一個實現相同的功能。 C#應用程序很快,而不是做兩次)。
要添加到現有的答案:
使用
.NET 4.0
,在VBA項目中使用C#dll而不注冊COM實際上非常簡單。
編輯 :我剛剛嘗試使用C:\\windows\\Microsoft.NET\\Framework\\v2.0.50727
的mscorlib.tlb
和mscoree.tlb
- 加載在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
(如果您運行的是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文件的位置(並且還需要有人確保它們在那里)。
問題是要使用SxS,您需要擁有exe來設置配置以加載SxS程序集。 您沒有“擁有”Access,雖然您可以放棄正確的配置以使其加載您的.NET COM內容沒有注冊,但這不是一個“好公民”的舉動。
如果你使用shimming變得棘手,你可以設置一個非托管DLL(或帶有dllexport的黑客C#類庫,例如看到這個 ),導出將加載.NET框架,創建一個COMVisible DispInterface管理的實例輸入並返回它(該方法應該返回IDispatch)。 然后寫一個VBA聲明到你的DLL導出函數(聲明為返回Object)。 如果這沒有意義,你可能不應該嘗試... :)我之前在類似的情況下做過這個,它確實有效,但我沒有一個樣本指向你。
C#庫不是常規DLL。 它們更像是在使用之前需要注冊的COM庫(就像ActiveX控件一樣); 特別是從非.NET代碼調用時。
(當然,除非事情發生了變化......)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.