Совместный интерфейс COM с C # и VBA

Я не говорю о вызове VBA COM с C # … наоборот!

То, что я хотел бы сделать, это вызвать библиотеку C #, используя VBA в MS Access, без регистрации DLL. Я играл с бок о бок в течение некоторого времени без успеха, и мне, наконец, пришло в голову, что mdb.manifest, вероятно, не является приемлемой заменой exe.manifest (возможно, очевидно, я знаю, но я пытался быть оптимистом).

Мой вопрос: возможно ли получить VBA для загрузки бокового компонента COM?

Или, есть ли другой способ использовать незарегистрированную библиотеку C # в Access?

(Прежде чем вы спросите, мои причины таковы: мне совершенно не разрешается доступ к реестру Windows моего клиента, поэтому он был впервые написан в Access. И мне нужно будет реализовать ту же функциональность в C #, и скорее не делайте этого дважды).

Вам не нужно владеть exe для использования SxS, SxS – это еще одно слово для контекста активации . Если вы можете импортировать соответствующие вызовы win32 в vba (и вы можете), вы можете использовать контекст активации api для загрузки файла манифеста.

Подробнее о предмете и некоторых примерах можно найти здесь .

Чтобы добавить к уже существующим ответам: с .NET 4.0 на самом деле довольно просто использовать C # dll в проекте VBA без регистрации COM.

EDIT : Я просто попробовал это с mscoree.tlb и mscoree.tlb которые находятся в C:\windows\Microsoft.NET\Framework\v2.0.50727 – загрузка сборки, скомпилированной в 3.5, и она работала отлично. Поэтому, видимо, вам не нужен .NET 4.0.

Ниже приведен пример использования C # dll в вашем проекте VBA. Он слегка изменен из этого ответа.

1) Добавьте ссылки на следующий тип libs вашего проекта VBA (Tools-> References):

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

(используйте папку Framework64, если вы работаете с 64-разрядным Office)

2) В своем проекте C # убедитесь, что вы добавили в свой class атрибут [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-взаимодействия». Это только для создания стандартного COM-объекта. Вам также не нужно проверять «Make Assembly COM Visible», если вы не хотите, чтобы вся assembly была видимой (что также устранит необходимость в 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, и запустите подпрограмму Test () в VBA.

Заметки:

Следует отметить, что одним из ограничений этого метода является то, что он не будет работать, если .DLL будет храниться на удаленном сетевом ресурсе. Одним простым решением было бы скопировать его в ту же локальную папку на каждом ПК, где он используется. Другим решением было бы включить двоичные файлы в проект Access / VBA Access и экспортировать MS-Access. Один из способов, который может быть выполнен, – сохранить их в Base64 в таблице или в электронной таблице, а затем преобразовать их и экспортировать в виде двоичных файлов.

Я смог получить раннюю привязку (и, следовательно, Microsoft IntelliSense) к работе, создав библиотеку типов, которая будет работать с DLL (с ​​помощью tlbexp), и добавив ссылку на TLB в моем проекте VBA, но это немного осложняет ситуацию потому что для вашего приложения VBA требуется знать, где находятся файлы DLL и TLB (а также требует, чтобы кто-то удостоверился, что они есть).

Проблема заключается в том, что для использования SxS вам необходимо владеть exe, чтобы настроить конфигурацию для загрузки сборки SxS. Вы не являетесь «владельцем» доступа, и, хотя вы можете отказаться от правильной конфигурации, чтобы заставить его загружать ваш .NET-материал без регистрации, это не было бы «хорошим гражданином».

Если вы запутались в shimming, вы можете настроить неуправляемую DLL (или взломанную библиотеку classов C # с помощью dllexport, см. Это , например) с экспортом, который загрузит платформу .NET, создаст экземпляр COMVisible DispInterface, управляемого введите и верните его (метод должен вернуть IDispatch). Затем напишите сообщение VBA в функцию экспорта DLL (объявленный как возвращаемый объект). Если это не имеет смысла, вы, вероятно, не должны пытаться … 🙂 Я сделал это раньше в подобной ситуации, и это действительно работает, но у меня нет образца, чтобы указать на вас.

Библиотеки C # не являются обычными DLL. Они больше похожи на библиотеки COM, которые должны быть зарегистрированы (как и элементы ActiveX) перед использованием; особенно при вызове из не-NET кода.

(Если, конечно, все не изменилось …)

Давайте будем гением компьютера.