2015-02-05 19 views
2

1) Возможно ли внедрить dll .net в базу данных Microsoft Access? В идеале я хочу, чтобы dll фактически встроена в базу данных доступа, поэтому она не может отсутствовать. Мне нужно получить доступ к нескольким API-интерфейсам из моей базы данных доступа.Вставить .Net dll в базу данных Microsoft Access

2) Если возможно, каковы ограничения? Я предполагаю, что база данных доступа должна использоваться на машине с установленной программой .net. Есть ли другие вопросы, которые я должен рассмотреть?

+2

Это, кажется, исключительно плохое решение любой проблемы, которая у вас есть. Почему бы вам не спросить о своей реальной проблеме? – nvoigt

+0

Вы можете сохранить слово или .exe или .dll внутри Access. Таким образом, при запуске Access вы наверняка можете проверить наличие DLL, а если не найти, вытащите их из локальной таблицы в Access и поместите DLL в том же каталоге, что и ваше приложение. Однако, как отмечалось до этого времени, вы вытаскиваете файлы .net (COM), они не могут использоваться Access. И в большинстве случаев вам также придется регистрировать такие COM-объекты, прежде чем их можно будет использовать - это означает, что пользователям потребуется достаточно прав для регистрации COM-объектов, если не используется подход «бок о бок» .net. –

ответ

5

Это на самом деле кажется 2 немного разными вопросами, чем те, которые были заданы, если я правильно его читаю: (1) Можете ли вы вставить двоичный файл в базу данных JET/ACE? и (2) Можете ли вы вызвать методы из .NET DLL из MS-Access?

  1. Да, вы можете встраивать двоичный файл в базу данных JET/ACE. Мой предпочтительный способ сделать это - прочитать файл как двоичный и кодировать как base64 в поле Memo.

Во-первых, вам нужно прочитать в двоичном файле в массив байтов. Это можно сделать с помощью Open или с помощью объекта ADODB.Stream. Затем вы кодируете массив байтов как строку Base64, и, наконец, вы записываете эту строку в таблицу. Чтобы экспортировать двоичный файл, вы делаете обратное.

Вот функции для преобразования массива в базе 64 (Source):

'Requires reference to Microsoft XML v3.0 
Private Function EncodeBase64(ByRef arrData() As Byte) As String 

    Dim objXML As MSXML2.DOMDocument 
    Dim objNode As MSXML2.IXMLDOMElement 

    ' help from MSXML 
    Set objXML = New MSXML2.DOMDocument 

    ' byte array to base64 
    Set objNode = objXML.createElement("b64") 
    objNode.dataType = "bin.base64" 
    objNode.nodeTypedValue = arrData 
    EncodeBase64 = objNode.Text 

    ' thanks, bye 
    Set objNode = Nothing 
    Set objXML = Nothing 

End Function 

Private Function DecodeBase64(ByVal strData As String) As Byte() 

    Dim objXML As MSXML2.DOMDocument 
    Dim objNode As MSXML2.IXMLDOMElement 

    ' help from MSXML 
    Set objXML = New MSXML2.DOMDocument 
    Set objNode = objXML.createElement("b64") 
    objNode.dataType = "bin.base64" 
    objNode.Text = strData 
    DecodeBase64 = objNode.nodeTypedValue 

    ' thanks, bye 
    Set objNode = Nothing 
    Set objXML = Nothing 

End Function 

И вот примеры того, как использовать эти Base64 функции импорта и экспорта двоичного файла в поле Memo, используя ADODB.Stream объект:

Function ImportBinary() 
    'Requires a reference to ActiveX Data Objects 2.8 or higher 
    Dim InputStream As ADODB.stream 
    Dim FileBytes() As Byte 

    Set InputStream = New ADODB.stream 
    InputStream.Type = adTypeBinary 
    InputStream.Open 
    InputStream.LoadFromFile ("A:\Binary\File\To\Import.dll") 
    FileBytes = InputStream.Read() 

    With CurrentDb().TableDefs("TableWithMemoField").OpenRecordset 
     .AddNew 
     !MemoField.Value = EncodeBase64(FileBytes) 
     .Update 
     .Close 
    End With 

    InputStream.Close 
End Function 

Function ExportBinary() 
    Dim OutputStream As ADODB.stream 

    Set OutputStream = New ADODB.stream 
    OutputStream.Type = adTypeBinary 
    OutputStream.Open 

    With CurrentDb().TableDefs("TableWithMemoField").OpenRecordset 
     OutputStream.Write DecodeBase64(!MemoField.Value) 
     .Close 
    End With 

    OutputStream.SaveToFile "A:\Binary\File\To\Export.dll" 

    OutputStream.Close 
End Function 

Кроме того, вы также можете вставить файл (ы) в OLE полей, или, в последних версиях Access также есть поле «Приложение». Я считаю, что это возможно.

  1. Да, можно вызвать методы из .NET DLL - см. here. В основном вы занимаетесь хостингом .NET runtime в Access.

Ограничение на то, что вы можете использовать только среду .NET 2.0 или 3.5 - несмотря на то, что на связанной странице говорится, что вы можете использовать 4.0. Насколько я знаю, нет простого способа размещения среды .NET 4.0+ в VBA. Если вы попытаетесь вызвать DLL 4.0+, вы получите сообщение об ошибке «сборка более новая, чем среда выполнения».

Да, вам также необходимо использовать его на машине, на которой установлены версии 2.0 и/или 3.5.

Кроме того, он не будет загружать DLL непосредственно из общего сетевого ресурса. Это ограничение .NET framework, которое можно преодолеть (link), но я не уверен, что это можно сделать при размещении DLL в Access.

Чтобы использовать «встроенную» DLL, вам необходимо экспортировать ее из базы данных, прежде чем использовать ее; хорошим местом будет временная папка пользователя.

EDIT: Относительно точки (2) - Я ранее писал, что вам не нужно выставлять свой класс C# в качестве COM, однако после тестирования я понял, что это неверно.Вам нужно объявить свой класс атрибутом [COMVisible(true)] (или реализовать интерфейс IDispatch), чтобы VBA правильно создавал экземпляр вашего класса - иначе CreateInstanceFrom ничего не вернет.

+0

Доступ должен потреблять .net 4.5 просто отлично. Если вы просто создаете объект класса vb.net и помечаете регистр для COM-взаимодействия, класс будет отображаться в «стандартном» списке ссылок Windows из редактора VBA (tools-> reference). Я использовал .net 4.5, это отлично работает с Access. Единственное предложение - ограничить (заставить) приложение .net запускать/компилировать как x86 (принудительный 32-разрядный). И не только потребуется экспорт .dll, но и regasm для регистрации и публикации .net как стандартного COM-объекта. Вы не можете создавать стандартные окна .dll с объектами COM .net - только COM. –

+0

@ AlbertD.Kallal Я думаю, вы говорите о чем-то немного другом. Используя метод COM, вы абсолютно правы - можно использовать более высокую платформу .NET. Но, как вы сказали, он требует регистрации, если не может использоваться реальный регистр SxS. Связанный с ответом [здесь] (http://stackoverflow.com/questions/1903220/side-by-side-com-interop-with-c-sharp-and-vba/13333819#13333819) фактически _hosts_ .NET. в Access, который немного отличается - он не требует рег. Однако в то время, когда я написал этот ответ, я немного путал свои концепции, думая, что я использую SxS. – transistor1

+0

Фактически, насколько я могу судить, этот связанный ответ просто позволяет вам потреблять COM-объект .net, не регистрируя его. Таким образом, это не «больше» или «меньше» для размещения приложения внутри Access, а не позволяет использовать обычный COM-объект .net. Однако это, безусловно, «большой» бонус, который не должен регистрировать объект .net. Поэтому я собираюсь изучить это, так как часто пользователи не имеют прав на регистрацию объектов .com (для них требуются изменения в реестре). Так что все-таки «замечательный» момент с вашей стороны, и если я смогу получить эту работу, я приму это для приложений Access, использующих объекты .net. –

Смежные вопросы