Бок о бок COM-взаимодействие с C# и VBA

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

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

мой вопрос: можно ли заставить VBA загружать параллельный COM-компонент?

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

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

4 ответов


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

больше на эту тему и некоторые примеры можно найти здесь.


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

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

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

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

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# убедитесь, что вы добавили [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 объект. Вам также не нужно проверять "сделать сборку com видимой", если вы не хотите, чтобы вся сборка была видимой (это также устранит необходимость ).

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 () sub в VBA.

Примечания:

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

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


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

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


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

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