Exchange 2000 提供透過 ADO 2.5 以上的版本存取的能力,讓 Universal Data Access 策略,也就是透過 OLE DB 可以讓任何應用程式存取任何資料得以推展到 Exchange 的資料存取。你可以利用結構化查詢語言(SQL)來存取 Exchange 2000 的資源。另外全文檢索的能力讓你可以找尋文件的內容,不管是一般的文件還是如 Office 產生出來的二進位文件。
Universal Data Access
使用 ADO 2.5 來存取 Exchange 2000 資料
ADO 2.5 新增的 Record 和 Stream 物件提供了存取 Web Storage 系統階層式資料的能力。
標準的 ADO 2.5 物件
Connection 物件
利用 ADO Connection 物件可以用來連結特別的 public 或 mailbox store,管理群組的工作,並可以讓 Record 和 Recordset 物件共享使用。當利用 Connection 物件連結到 Exchange 2000 時,必須要透過設定 Provider 等於 ExOLEDB.DataSource 來使用 OLE DB Provider for Exchange。
程式碼範例如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/"
.BeginTrans
'完成資料存取的動作
.CommitTrans
.Close
End With
Recordset 物件
Recordset 物件代表著查詢結果,通常是從資料庫查詢回來的記錄。程式碼範例如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/"
End With
Dim rst As Recordset
Set rst = CreateObject("ADODB.Recordset")
Dim strSQL As String
strSQL = "SELECT ""urn:schemas:mailheader:subject"" FROM " & _
"""http://uiex2k/exchange/administrator/收件匣/"" WHERE ""DAV:ishidden""=FALSE"
rst.Open strSQL, cnn
Debug.Print "記錄筆數:" & rst.RecordCount
With rst
While Not .EOF
Debug.Print .Fields("urn:schemas:mailheader:subject")
.MoveNext
Wend
End With
結果
記錄筆數:5
Q2.TXT
test.txt
test123
test
=?big5?B?xXeq76jPpc4gTWljcm9zb2Z0IE91dGxvb2sgMjAwMCE=?=
注意 雖然 OLE DB Provider for Exchange 支援大多數的 ADO 物件的功能,但仍有部分功能不支援,如設定使用者帳號密碼來完成 impersonation,cursor type 或是 record lock 選項,以及巢狀交易(nested transaction)等等。
Persisting Recordset 物件
ADO 2.1 版之後支援將內含的資料以 XML 的格式儲存
程式碼範例如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/"
End With
Dim rst As Recordset
Set rst = CreateObject("ADODB.Recordset")
Dim strSQL As String
strSQL = "SELECT ""DAV:href"",""urn:schemas:mailheader:subject"" FROM " & _
"""http://uiex2k/exchange/administrator/收件匣/"" WHERE ""DAV:ishidden""=FALSE"
rst.Open strSQL, cnn
rst.Save "M:\EX2K.UDNGROUP.COM.TW\MBX\Administrator\收件匣\res.xml", adPersistXML
ADO 2.5 新增的物件
Record 物件
利用 Record 物件可以完整存取 Web Storage 系統內的任何資源,包含資源的屬性所成的群組或是它相關的資料串流(stream)。Record 物件可以呈現或管理資料,如資料匣或檔案系統內的檔案,或是訊息系統內的電子郵件。Record 也可以表現 Recordset 物件內的一筆記錄。利用 URL 可以將 Record 物件直接連結到 Web Storage 系統內的資源。
要將資源連結到 Record 物件,可以使用 Open 方法。當你使用 Open 方法時,可以設定 Mode 參數,以設定存取的權限。例如設定 Mode 等於 adModeRead、adModeReadWrite 或 adModeShareExclusive。以下是修改在 Web Storage 系統內資源的 author 屬性
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/"
End With
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
rec.Open "http://uiex2k/exchange/administrator/收件匣/book1.xls", cnn, adModeReadWrite
rec.Fields("urn:schemas-microsoft-com:office:office#author") = "Byron"
rec.Fields.Update
譯者註 這個作者與一般 Office 文件的摘要資訊內的作者似乎不同,因為兩個設定互不影響。
Stream 物件
利用 Stream 物件可以呈現檔案的內容。你可以利用 Stream 物件來讀取或寫入文字或二進位格式的檔案。
要開啟 Stream 物件可以利用本身的 Open 方法,或是利用 Record 物件搭配 adDefaultStream。
以下程式碼利用 Stream 與 Record 物件來開啟
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/"
End With
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
rec.Open "http://uiex2k/exchange/administrator/收件匣/res.xml", cnn
'以 Record 物件的 adDefaultStream 開啟 Stream 物件
Dim stm As ADODB.Stream
Set stm = rec.Fields(adDefaultStream).Value
stm.SaveToFile "M:\EX2K.UDNGROUP.COM.TW\MBX\Administrator\收件匣\test.txt", adSaveCreateOverWrite
'以 Stream 物件的 Open 方法開啟
Dim stm2 As ADODB.Stream
Set stm2 = CreateObject("ADODB.Stream")
stm2.Open rec, adModeRead, adOpenStreamFromRecord
以 Record 物件建立、複製和刪除資源
除了利用 ADO 的物件來開啟 Web Storage 系統的資源,你也可以利用 ADO 來執行 Web Storage 系統內的記錄維護動作,如建立、複製、移動或刪除資源。
建立檔案和資料匣
你可以利用 Record 物件來建立檔案和資料匣。 Record 的 Open 方法可以利用 CreateOptions 參數來決定是建立還是開啟一個檔案或資料匣。下表列出 CreateOptions 參數
參數列舉 | 說明 |
adCreateCollection | 在定義的 URL 建立一個新的集合(collection)而非開啟舊有的集合 |
adCreateNonCollection | 在定義的 URL 建立一個新的 Record |
adCreateOverwrite | 在定義的 URL 建立一個資源或集合,若有已經存在的資源就覆蓋過去。 |
adFailIfNotExists | 開啟已經存在的資源或是集合,若不存在就傳回錯誤 |
adOpenIfExists | 開啟已經存在的資源或是集合,若不存在不要傳回錯誤 |
以下程式碼在公共資料匣建立一個 test 資料匣
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/public"
End With
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
rec.Open "http://uiex2k/public/test", cnn, adModeReadWrite, adCreateCollection + adCreateOverwrite
複製和移動資源
你可以利用 Record 物件的 CopyRecord 和 MoveRecord 方法來從一個地方複製和移動資源到另外一個地方。CopyRecord 將資源從一個 URL 複製到另外一個 URL,而 MoveRecord 則會刪掉原來 URL 位置的資源。
當複製或移動時,可以利用 adCopyOverWrite 和 adMoveOverWrite 來設定目的端若已經存在資源時,是否要覆蓋。
程式碼如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "EXOLEDB.DataSource"
.Open "http://uiex2k/public"
End With
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
With rec
.Open "http://uiex2k/public/test", cnn, adModeReadWrite
.MoveRecord "http://uiex2k/public/test/aaa.eml", _
"http://uiex2k/public/test/subtest/aaa.eml", , , adMoveOverWrite
End With
注意 若你是對集合做複製或移動時,所有子物件都會一起動作
刪除資源
利用 Record 物件的 DeleteRecord 方法可以刪除在 Web Storage 系統的資源,若要如此做,先開啟要被刪除的資源,再呼叫 DeleteRecord 方法。
程式碼範例如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "EXOLEDB.DataSource"
.Open "http://uiex2k/public"
End With
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
With rec
.Open "http://uiex2k/public/test/subtest/aaa.eml", cnn, adModeReadWrite
.DeleteRecord
End With
利用 GetChildren 方法來瀏覽 Web Storage 系統資料
在 Web Storage 系統中的資訊是分散在多個資料庫中,可能同時在 private 和 public stores。這些資料庫包含許多相關的資料表(table)。例如 folder 資料表會儲存 folders 的狀況,而其他的資料表會存放在 folders 內的 item。
Recordset 物件代表每一個資料表,而 Record 物件則代表了其中獨立的記錄,如 folder 或 item。因為 Web Storage 系統是基於階層式的資料庫,folders 和 items 可能同時是 Records 和 Recordsets。藉由 URLs 和 ADO 物件組合使用,你可以存取 Web Storage 系統內的各種內容。
展開使用者的 Mailbox
在上圖中,Mailbox 1 以一個 ADO Record 物件代表,藉由呼叫 Record 的 GetChildren 方法可以獲得直屬下層所有的物件,以 Recordset 表示。這個 Recordset 包含了 mailbox 產生時標準的 folders(如 Inbox、Contacts、Calendar 和 Sent Items)。
展開使用者的 Contact Folder
Recordset 包含了獨立的 Record,每一個 folder 都是一個 Record 可以被獨立地存取。在 Contact Folder 以 Record 傳回後,可以再一次利用 GetChildren 方法來取得 folder 內所有的聯絡人記錄。這時又會產生一個新的 Recordset 物件,以代表所有的聯絡人。
使用 Stream 物件
你可以利用 Stream 物件來存取 Exchange 2000 的附件和檔案,透過 Read/Write 來操作二進位或標準文字檔。
存取檔案
當你開啟了 Stream 物件,你可以維護開啟的檔案內容,首先利用 Type 屬性來設定資料的型態,如果檔案包含文字資料,透過 Charset 屬性設定字元集。
Type 屬性的預設值是 adTypeText,也就是文字型態。如果你想要讀寫二進位的資料,你要設定為 adTypeBinary。若是文字檔案,你可以定義 Charset 屬性,預設是 "unicode" ,可以改成 "ancii"、"iso-8858-1" 或其他 Window 2000 註冊可以了解的字元集等等。
從檔案讀取資料
要讀取檔案的資料可以透過 Read 或是 ReadText 方法
- 使用 Read 方法來讀取二進位的資料流,如 Word 的文件,你可以選擇性地設定要讀取的位元組數
- 使用 ReadText 方法來讀文件資料,你可以設定是讀取整份文件,一行文字或是字元的數目。在 ReadText 方法中只能向前讀取,不可以回頭讀。
程式碼範例如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/"
End With
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
rec.Open "http://uiex2k/exchange/administrator/收件匣/res.xml", cnn
Dim stm As ADODB.Stream
Set stm = CreateObject("ADODB.Stream")
With stm
.Open rec, adModeRead, adOpenStreamFromRecord
.Type = adTypeText
.Charset = "big5"
Text1.Text = .ReadText(adReadAll)
End With
利用 URLs 來存取資源
使用 File: 和 HTTP: Schemes
使用 File: 和 HTTP: schemes 有不同的 URL 結構。透過伺服器端的 OLE DB provider 你可以同時使用 File: 和 HTTP: schemes 來定義 folders 和 items,但若使用 Hypertext Transfer Protocol/Web Distributed Authoring and Versioning(HTTP/WebDAV) 協定存取時,只能使用 HTTP: scheme 來定位。
使用 File: Scheme
以 File: scheme 來建立 URLs 時,使用 OLE DB provider for Exchange,URL 的格式如下
-
存取 public folder 的格式
file://./backofficestorage/domain-name/public-folder-tree-name/path - 存取使用者的 mailbox folder 的格式
file://./backofficestorage/domain-name/MBX/user-alias/path
程式碼範例如下
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
rec.Open "file://./backofficestorage/ex2k.udngroup.com.tw/PUBLIC FOLDERS/Hello/Exchange 2000 開發簡介.doc"
注意 OLE DB Provider for Exchange 以 OLE DB root binder 註冊 "File:OLE DB URL" namesapce,所以在使用 OLE DB,ADO 2.5 或是 CDO for Exchange 2000 Server 物件時,若使用 File: 這種 URL Scheme 不需要額外宣告。
使用 HTTP: Scheme
當你使用 HTTP: Scheme 建製 URL 時,遵循相同的方式,但可以透過 HTTP 協定來存取。URL 結構如下
http://servername/virtual-directory/virtual-path
值得注意的是 File: scheme 用得是原有的檔案路徑名稱,而 HTTP: 用得是虛擬路徑名稱。所有的私人信箱虛擬路徑名稱開頭是 exchange,而公共資料匣的開頭是 Public。以下是兩個範例
http://uiex2k/PUBLIC/Hello/
http://uiex2k/exchange/administrator/%E6%94%B6%E4%BB%B6%E5%8C%A3/
當使用 HTTP: scheme 時必須定義 OLE DB Provider for Exchange 連結到 ExOLEDB.DataSource 介面,所以程式碼撰寫如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/"
End With
注意 預設註冊的 HTTP: scheme 的 Provider 是 OLE DB Provider for Internet Publishing(MSDAIPP),如果你不指定,使用的就是這個 Provider。CDO 不支援這個 Provider,它的效率也比較不好。
使用 HTTP: Scheme 的好處
當你透過 HTTP: scheme 並明確建立 Connection 物件來存取資源或集合時,你可以獲得下列好處是 File: 所沒有的
- 交易管理
可以定義多個資料處理在同一個 OLE DB 的交易管理中,以保證一起完成或一起失敗
注意 OLE DB 在 Exchange 2000 的交易管理不可以跨多個資料庫 stores
- 相對 URLs
當你建立 Connection 物件並瀏覽 Exchange 2000 資料庫的階層架構時,你可以使用相對的 URLs
- Errors
Connection 物件的 Errors 集合物件會包含 ADO 運作時所發生的錯誤。
使用相對的 URLs
範例如下
Dim cnn As ADODB.Connection
Set cnn = CreateObject("ADODB.Connection")
With cnn
.Provider = "ExOLEDB.DataSource"
.Open "http://uiex2k/exchange/administrator/收件匣"
End With
Dim rec As ADODB.Record
Set rec = CreateObject("ADODB.Record")
rec.Open "./agenda.eml", cnn
Debug.Print rec.Fields("DAV:href")
rec.Close
rec.Open "../", cnn
Debug.Print rec.Fields("DAV:href")
使用 SQL 查詢來存取 Exchange 2000 的資料
你可以使用熟悉的 SQL 來搜尋 Web Storage 系統,語法是以 Microsoft Indexing Service Query Processor 定義的為基礎。
Microsoft Indexing Service 搜尋引擎以系統帳號(system account)來執行動作,這讓它可以讀取所有的 stores 包括個人資料夾。要維護安全,從 SQL 查詢傳回的 Rowset 物件會比對 Access control lists(ACLs),讓傳回的記錄是使用者可以讀取的。
設定索引的屬性或實做全文檢索可以提昇查詢效能
注意 下列屬性在查詢時是不正確的,因為它們的值是在要求時才計算出來的,所以無法以此搜尋
DAV:lockdiscovery,DAV:resourcetype 和 DAV:searchrequest
SQL 語法的 SCOPE 元素
利用 SCOPE 來定義查詢的範圍
透過 SCOPE 元素可以定義 URLs 查詢的資料夾深度,若只要本層可用 Shallow ,若要子層可用 Deep。格式如下
SCOPE('shallow traversal of "url1"',['shallow traversal of "URL2"'])
或是
SCOPE('deep traversal of "url1"',['deep traversal of "URL2"'])
範例如下
Dim oRec As ADODB.Record
Dim sURL As String
Dim sSQL As String
Dim oRst As ADODB.Recordset
Set oRec = CreateObject("ADODB.Record")
Set oRst = CreateObject("ADODB.Recordset")
sURL = "file://./backofficestorage/EX2K.UDNGROUP.COM.TW/mbx/administrator/收件匣/"
oRec.Open sURL
'建立 Recordset 的 SQL 查詢
sSQL = "select "
sSQL = sSQL & " ""urn:schemas:mailheader:content-class"""
sSQL = sSQL & ", ""DAV:href"""
sSQL = sSQL & ", ""DAV:displayname"""
sSQL = sSQL & " from scope ('shallow traversal of " & Chr(34)
sSQL = sSQL & sURL & """') "
sSQL = sSQL & " WHERE ""DAV:ishidden"" = false"
oRst.Open sSQL, oRec.ActiveConnection
List1.Clear
List1.AddItem "Administrator 的個人資料夾有:"
Do While Not oRst.EOF
List1.AddItem " " & oRst.Fields("DAV:displayname")
oRst.MoveNext
Loop
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· AI Agent爆火后,MCP协议为什么如此重要!
· dotnet 源代码生成器分析器入门
· Draw.io:你可能不知道的「白嫖级」图表绘制神器
· ASP.NET Core 模型验证消息的本地化新姿势
· Java使用多线程处理未知任务数方案