Совместное COM-взаимодействие с C # и VBA - PullRequest
7 голосов
/ 14 декабря 2009

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

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

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

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

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

Ответы [ 4 ]

12 голосов
/ 11 ноября 2012

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

РЕДАКТИРОВАТЬ : я только что попробовал это с mscorlib.tlb и mscoree.tlb, которые находятся в C:\windows\Microsoft.NET\Framework\v2.0.50727 - загрузка сборки, скомпилированной в 3.5 - и она работала просто отлично. Очевидно, вам не нужен .NET 4.0.

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

1) Добавьте ссылки на следующий тип библиотек вашего проекта 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», если только вы не хотите, чтобы вся сборка была видимой (это также устранит необходимость в атрибуте 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 и экспортировать их в MS-Access. Одним из способов достижения этого было бы сохранение их в Base64 в таблице или электронной таблице, а затем их преобразование и экспорт в двоичный файл.

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

3 голосов
/ 14 января 2010

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

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

1 голос
/ 17 декабря 2009

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

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

0 голосов
/ 14 декабря 2009

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...