1) 是否可以将 .net dll 嵌入到 Microsoft Access 数据库中?理想情况下,我希望该 dll 实际上被嵌入到访问数据库中,以便它不会丢失。我需要从我的访问数据库中访问一些 API。
2) 如果可能的话,有哪些限制?我假设访问数据库必须在已安装 .net 的计算机上使用。还有其他问题需要考虑吗?
1) 是否可以将 .net dll 嵌入到 Microsoft Access 数据库中?理想情况下,我希望该 dll 实际上被嵌入到访问数据库中,以便它不会丢失。我需要从我的访问数据库中访问一些 API。
2) 如果可能的话,有哪些限制?我假设访问数据库必须在已安装 .net 的计算机上使用。还有其他问题需要考虑吗?
首先,您需要将二进制文件读入一个字节数组中。这可以使用 Open
或使用 ADODB.Stream
对象来完成。然后,您将字节数组编码为Base64字符串,最后将该字符串写入表格。要导出二进制文件,则执行相反操作。
以下是将字节数组转换为Base 64的函数:
(源代码):'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还有一个“附件”字段。我相信这是可行的。
局限性在于,您只能托管.NET 2.0或3.5运行时-尽管链接页面说您可以使用4.0。据我所知,在VBA中没有简单的方法来托管.NET 4.0+运行时。如果尝试调用4.0+ DLL,则会出现“程序集比运行时新”的错误。
是的,您还需要在安装了2.0和/或3.5运行时的计算机上使用它。
此外,它不会直接从网络共享加载DLL。这是.NET框架的限制,可以克服(link),但我不确定在Access中托管DLL时是否可以这样做。
为了使用“嵌入式”DLL,在使用之前需要从数据库中导出它;一个好地方是用户的临时文件夹。
编辑:关于第(2)点-我之前写过您不需要将C#类公开为COM,但是在测试后,我意识到这是不正确的。您需要使用[COMVisible(true)]
属性(或实现IDispatch接口)声明类,以便VBA正确实例化您的类-否则CreateInstanceFrom
将返回Nothing。