在自動化程序中使用早期繫結與晚期繫結

文章翻譯 文章翻譯
文章編號: 245115 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

結論

如何繫結到自動化伺服器對於您的程式會有許多影響,例如效能、彈性及維護性。

本文將告訴您適用於自動化用戶端的繫結類型,並會評估每個方法的優缺點。

其他相關資訊

自動化是一個處理程序,其中會有一個軟體元件使用 Microsoft 的元件物件模型 (COM) 與另一個軟體元件通訊,及/或控制另一個軟體元件。它是 Visual Basic 或 Visual Basic for Applications 之類的語言所使用大部分跨元件通訊的基礎,且已成為大部分程式的標準組件。

在以前的環境中,自動化物件是指任何支援 IDispatch 介面的物件。此介面允許用戶端在執行階段呼叫方法和屬性,而不必知道其在設計階段進行通訊的真正物件;此處理程序稱為晚期繫結。不過,現在 自動化物件一詞已可套用至幾乎任何 COM 物件,即使那些不支援 IDispatch (而因此無法作晚期繫結) 的物件也一樣。本文假設您要自動化的物件同時支援兩種繫結方法。

何謂繫結?

繫結是把程式設計師撰寫的函數呼叫,與實作該函數的實際程式碼 (內部或外部),進行配對的一種程序。它是在應用程式編譯時完成的,在執行程式碼之前,該程式碼中呼叫的所有函數都必須先完成繫結。

若要了解此程序,請將「繫結」想像成書籍的撰寫與出版程序。想像程式碼就像書籍的文字,您在特定段落寫下類似「如需詳細資訊,請參閱第 12 章第 x 頁」的文字。在書籍完成之前,您無法知道頁碼為何,所以,必須將書籍的全部頁面繫結在一起,並且將正確的頁碼插入到段落中,段落才能如預期的方式呈現。在參照書籍的其他部分之前,您必須先等書籍完成「繫結」。

繫結軟體是相似的。您需要同時取出組成程式碼的各個部分之後,才可以讀取該程式碼。繫結是使用記憶體位址 (更精確地說,是記憶體位移) 來取代函數名稱的動作,亦即呼叫函數時,程式碼將會「跳至」記憶體位址。以 COM 物件而言,該位址為該物件在指標表格 (稱之為 v-table) 中所保留的記憶體位移。當 COM 函數繫結時,是透過 v-table 完成繫結。

COM 物件的結構很簡單。當程式碼保留物件的參考時,它會保留 v-table 頂端的間接指標。v-table 是記憶體位址的陣列,其中每個項目為可以對該物件呼叫的不同函數。若要對 COM 物件呼叫第三個函數,您必須在表格中往下跳到第三個項目,然後跳至該處給定的記憶體位置。這樣就會執行該函數的程式碼,完成時,則會返回並準備執行程式碼的下一行。

+-[程式碼]------------+  +.................................[COM 物件]...+
|                   |  : +-------------+                                :
|Set obj = Nothing -|--->| obj 指標 |                                :
|                   |  : +-|-----------+                                :
+-------------------+  :   |   +-----------------+                      :
:   +-->| v-table 指標 |                      :
                       :       +--|--------------+                      :
                       :          |                                     :
                       :          |  +----------------------------+     :
:  (第 3 個)   |  | 函數 1 位址指標 |     :
: (位移) |  +----------------------------+     :
:          |  | 函數 2 位址指標 |     :
                       :          |  +----------------------------+     :
:          +->| 函數 3 位址指標 |     :
                       :             +----------------------------+     :
                       +................................................+

				
上述範例顯示在釋放 COM 物件時會發生什麼狀況。因為所有的 COM 物件均繼承自 IUnknown,所以表格中的前三個項目均為 IUnknown 的方法。當您需要釋放某物件時,程式碼會在 v-table 中呼叫第三個函數 (IUnknown::Release)。

幸好,此工作是由 Visual Basic 在幕後完成。身為 Visual Basic 程式設計師,您並不需要直接處理 v-table。然而,此結構為所有 COM 物件的繫結方式,您必須熟悉以了解繫結。

早期繫結

上述範例即是所謂的早期 (或 v-table) 繫結。對於所有的 COM 物件而言,此繫結形式會在呼叫 COM 物件的 IUnknown 介面時發生。但是物件的其他函數又是如何呢?您該如何呼叫其 Refresh 方法或其 Parent 屬性?這些通常是針對特定物件的自訂函數。如果在 v-table 中無法假設其位址,則要如何尋找其函數位址以呼叫它們?

當然,答案要根據您事先是否知道該物件的 v-table 內容而定。如果事先知道,您就可以對該物件的自訂方法執行您對其 IUnknown 方法所執行的相同早期繫結程序。這就是一般所謂的「早期繫結」。

若要對某物件使用早期繫結,您需要知道其 v-table 內容。在 Visual Basic 作業中,您可以藉由在型別程式庫中新增參考,以描述該物件、其介面 (v-table) 以及所有可以對該物件呼叫的函數,來達到此目的。完成之後,即可宣告該物件為特定型別,然後使用 v-table 來設定及使用該物件。比方說,如果想要使用早期繫結以自動化 Microsoft Office Excel,則可以利用 [專案|參考] 對話方塊,在 [Microsoft Excel 8.0 物件程式庫] 中新增參考,然後宣告變數為 "Excel.Application" 型別。從此以後,所有對於該物件變數的呼叫將為早期繫結:
' Set reference to 'Microsoft Excel 8.0 Object Library' in
' the Project|References dialog (or Tools|References for VB4 or VBA).

' Declare the object as an early-bound object
  Dim oExcel As Excel.Application

  Set oExcel = CreateObject("Excel.Application")

' The Visible property is called via the v-table
  oExcel.Visible = True
				
這個方法在大部分的情況下都很好用,但是如果您不知道在設計階段將使用的物件時,那該怎麼辦?例如,如果您需要與 Excel 的多個版本進行溝通,或是與「不明」的物件進行溝通時,那該怎麼辦?

晚期繫結

COM 有包含 IDispatch。實作 IDispatch 的物件,據說具有分配介面 (Dispinterface) (如果這是所支援的唯一介面) 或雙重介面 (Dual Interface) (如果也具有可供早期繫結的自訂介面)。繫結至 IDispatch 的用戶端稱之為「晚期繫結」,因為其所呼叫的屬性或方法,是在執行階段使用 IDispatch 的方法找出而加以決定的。以稍早的書籍範例而言,您可以把它想像成引導您翻到目錄的註腳,也就是說,您必須在「閱讀時」才「查詢」頁碼,而不是已經將它列印在文字的位置上。

介面是由兩個函數所控制:GetIDsOfNames 與 Invoke。第一個會將函數名稱 (字串) 對應到代表該函數的識別碼 (稱為 dispid)。知道想要呼叫之函數的 ID 位址之後,您就可以使用 Invoke 函數呼叫它。這種呼叫方法的形式稱為「晚期繫結」。

再次提醒您,在 Visual Basic 作業中,您將藉由物件宣告來指定物件的繫結方式。若您宣告物件變數為「物件」,您實際上是指示 Visual Basic 使用 IDispatch,因此為晚期繫結:
' No reference to a type library is needed to use late binding.
' As long as the object supports IDispatch, the method can 
' be dynamically located and invoked at run-time.

' Declare the object as a late-bound object
  Dim oExcel As Object

  Set oExcel = CreateObject("Excel.Application")

' The Visible property is called via IDispatch
  oExcel.Visible = True
				
如您所見,程式碼的其餘部分是相同的。早期繫結與晚期繫結之間的唯一差異 (根據您撰寫的程式碼),在於變數宣告。

值得一提的是,所謂「晚期繫結」是指呼叫的函數而非呼叫的方式。大致上,從稍早討論的繫結中,您應該已注意到 IDispatch 本身即為「早期繫結」:也就是說,Visual Basic 會透過 v-table 項目 (IDispatch::Invoke) 發出設定 Visible 屬性的呼叫,就像對任何 COM 呼叫一樣。COM 物件本身會負責將呼叫轉送至正確的函數,以使 Excel 顯示。此間接性會允許 Visual Basic 用戶端進行編譯 (也就是繫結至一個有效的函數位址),但是仍然不知道將實際執行工作的函數。

Dispid 繫結

有些自動化用戶端 (最著名的是 MFC 與 Visual Basic 3.0,但是也有涉及 ActiveX 控制項的 Visual Basic 5.0 及 6.0) 會使用晚期繫結的混合形式,稱之為 dispid 繫結。如果在設計階段已知 COM 物件,則對於所呼叫函數的 dispids 可以直接快取並傳遞至 IDispatch::Invoke,而不必在執行階段呼叫 GetIDsOfNames。如此可大幅提高效能,因為每個函數只需要發出一個呼叫,而不必發出兩個 COM 呼叫。

在 Visual Basic 5.0 或 6.0 中,Dispid 繫結並非一般可選擇的選項。它使用於在型別程式庫中參考但不包含自訂介面的物件 (也就是僅具有分配介面的物件),以及彙總 ActiveX 控制項,但一般而言,Visual Basic 會在您通常使用 dispid 繫結的地方使用早期繫結。

我應該使用哪一種形式的繫結?

這個問題的答案有一半取決於專案的設計。在幾乎所有案例中,Microsoft 都建議使用早期繫結。然而,在有些情況下則應該選擇晚期繫結。

早期繫結為建議的方法。它的執行效能最佳,因為應用程式將直接繫結至所呼叫函數的位址,且進行執行階段查?時也不會有額外的負荷。在整體執行速度方面,它至少比晚期繫結快兩倍。

早期繫結也提供型別安全性。當您在元件的型別程式庫中設定參考之後,Visual Basic 會提供 IntelliSense 支援,以協助您正確地編碼每一個函數。如果參數的資料型別或傳回值不正確,Visual Basic 也會警告您,這樣即可在撰寫程式碼和進行偵錯時節省很多時間。

當物件的介面在設計階段仍為未知時,晚期繫結仍然很有用。如果應用程式需要與多個未知伺服器進行溝通,或需要使用名稱叫用函數 (例如使用 Visual Basic 6.0 CallByName 函數),則您需要使用晚期繫結。如果元件對於不同版本的介面做了不正確的修改或調整,則晚期繫結對於解決元件對於多個版本之相容性問題也很有幫助。

早期繫結有多項優點,因此應該盡可能選用。

維護多個版本之間的相容性

如果您使用的元件不會隨安裝套件而轉散發,且您無法確認將在執行階段用以通訊的版本,則您應該特別採用早期繫結,並繫結到與該元件所有版本相容的介面,或 (在某些情況下) 使用晚期繫結來呼叫一個可能存在於特定版本中的方法,如果該方法不存在於用戶端系統上已安裝的版本中,則再以正常方式失敗。

Microsoft Office 應用程式就是此種 COM 伺服器的最佳範例。Office 應用程式通常會展開其介面,以新增新的功能或在版本之間更正先前的缺點。如果您需要將 Office 應用程式自動化,建議您早期繫結至預期要安裝在用戶端系統上之產品的最早版本。比方說,如果您需要自動化 Excel 95、Excel 97、Excel 2000 及 Excel 2002,則應該使用 Excel 95 (XL5en32.olb) 的型別程式庫,以維持與其他三種版本的相容性。

Office 應用程式亦示範具有大型雙重介面的物件模型,在某些平台上可能具有封送限制。若要讓您的程式碼在所有平台上都能順利執行,請使用 IDispatch。 如需有關使用 Office 應用程式時維護相容性的詳細資訊,請按一下下面的文件編號,檢視「Microsoft 知識庫」中的文件:
247579 Use DISPID binding to automate Office applications whenever possible

?考

如需有關 COM、v-table 及自動化的詳細資訊,請參閱下列書籍:
Rogerson, Dale, Inside COM, MSPRESS, ISBN:1-57231-349-8.

Curland, Matt, Advanced Visual Basic 6, DevelopMentor, 0201707128。

屬性

文章編號: 245115 - 上次校閱: 2007年11月20日 - 版次: 7.1
這篇文章中的資訊適用於:
  • Microsoft Office Ultimate 2007
  • Microsoft Office Enterprise 2007
  • Microsoft Office Professional 2007
  • Microsoft Office Professional Plus 2007
  • Microsoft Office Standard 2007
  • Microsoft Office Home and Student 2007
  • Microsoft Office Basic 2007
  • Microsoft Office Standard Edition 2003
  • Microsoft Office XP Developer Edition
  • Microsoft Office 2000 Developer Edition
  • Microsoft Visual Basic 5.0 Professional Edition
  • Microsoft Visual Basic 6.0 Professional Edition
  • Microsoft Visual Basic 5.0 Enterprise Edition
  • Microsoft Visual Basic 6.0 Enterprise Edition
關鍵字:?
kbinfo kbautomation KB245115
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com