将 .Net dll 嵌入到 Microsoft Access 数据库中

Embed .Net dll into Microsoft Access Database

1) 是否可以将 .net dll 嵌入到 Microsoft Access 数据库中?理想情况下,我希望 dll 实际上嵌入到访问数据库中,因此它不会丢失。我需要从我的访问数据库中访问一些 API。

2) 如果可以,有什么限制?我假设访问数据库必须在安装了 .net 的机器上使用。还有其他我应该考虑的问题吗?

如果我没看错的话,这实际上似乎是 2 个与所问问题略有不同的问题:(1) 你能在 JET/ACE 数据库中嵌入一个二进制文件吗?和 (2) 您可以从 MS-Access 的 .NET DLL 调用方法吗?

  1. 是的,您可以将二进制文件嵌入到 JET/ACE 数据库中。我的首选方法是在 Memo 字段中将文件读取为二进制文件并编码为 base64。

首先,您需要将二进制文件读入字节数组。这可以使用 Open 或使用 ADODB.Stream 对象来完成。然后,将字节数组编码为 Base64 字符串,最后将该字符串写入 table。要导出二进制文件,您需要执行相反的操作。

以下是将字节数组转换为 Base 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 函数使用 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 也有一个 "Attachment" 字段。我相信可以使用它。

  1. 是的,可以从 .NET DLL 调用方法 - 请参阅 here。您实际上在做的是在 Access 中托管 .NET 运行时。

限制是您只能托管 .NET 2.0 或 3.5 运行时——尽管链接页面说您可以使用 4.0。据我所知,没有简单的方法可以在 VBA 中托管 .NET 4.0+ 运行时。如果您尝试调用 4.0+ DLL,您将收到 "the assembly is newer than the runtime".

效果的错误

是的,您还需要在安装了 2.0 and/or 3.5 运行时的机器上使用它。

此外,它不会直接从网络共享加载 DLL。这是 .NET 框架的限制,可以克服 (link),但我不确定在 Access 中托管 DLL 时是否可以做到这一点。

为了使用"embedded" DLL,在使用前需要从数据库中导出;一个好的地方是用户的临时文件夹。

编辑: 关于第 (2) 点——我之前曾写过,您不需要将 C# class 公开为 COM,但是,在测试之后我意识到这是不正确的。您确实需要使用 [COMVisible(true)] 属性声明 class(或实现 IDispatch 接口),以便 VBA 正确实例化您的 class-- 否则 CreateInstanceFrom 将 return 没有。