ADSI 提供者的實作問題

若要實作 ADSI 介面,請先實作 COM 介面 IDirectoryObject 藉由提供此介面作為最小的額外負荷層,您可以提供用戶端應用程式,以直接從目錄存取目錄物件,而不是透過將網路效能優化之 ADSI 快取所需的控件。 使用此介面也會提供您自己的實作最具彈性。

其次,實作基本的 ADSI 介面、IADs、IADsContainerIADsCollection IADsPropertyValue、IADsPropertyEntryIADsPropertyList 屬性快取介面。 IADsGroupIADsMembers 也是系統管理軟體經常需求的介面。

第三,如果您的目錄服務具有基礎架構,請實作架構管理介面:IADsClassIADsPropertyIADsSyntax。 如果沒有基礎架構,請使用這些介面來抽象目錄服務所使用的類別和屬性。 架構可用來將目錄服務的功能發佈至 ADSI 用戶端。

集合

ADSI 提供者元件可以遵循三個模型之一,以在列舉期間快取集合。 當集合中的物件從 ADSI 外部的基礎目錄服務中刪除時,快取模型的選擇會決定 ADSI 的行為。

快取模型包括:

  • 預先快取的集合。 當呼叫 IADsCollection::get__NewEnum 以建立新的列舉值物件時,會從基礎目錄服務擷取物件實例的集合。 如果從基礎目錄服務中刪除所擷取集合中 Active Directory 物件實例的來源物件,用戶端將無法辨識刪除,直到 IADs::GetInfo 或 IADs::SetInfo 嘗試存取集合為止。
  • 以累加方式快取的集合。 呼叫 IEnumVARIANT::Next,集合會從基礎目錄服務擷取一個物件。 IEnumVARIANT::Reset 會回到快取 中集合的開頭,而 IEnumVARIANT::Next 會傳回快取的物件,直到快取結束為止,此時會從基礎存放區新增新的物件。 當 Active Directory 物件實例位於快取中時,除非 IADs::GetInfo 或 IADs::SetInfo 嘗試存取對象,否則用戶端不會察覺其從基礎目錄服務刪除。
  • 未快取的集合。 呼叫 IEnumVARIANT::Next,集合會從基礎目錄服務擷取一個物件。 IEnumVARIANT::Reset 會回到基礎存放區中集合的開頭。 IEnumVARIANT::NextIEnumVARIANT::Reset 作業無法擷取已刪除的物件,因為物件會隨選從基礎目錄服務擷取。 只會快取目前的物件;如果刪除目前的物件,用戶端將不會察覺其從基礎目錄服務刪除,直到 IADs::GetInfo 或 IADs::SetInfo 嘗試存取物件為止。

不論快取模型為何,請注意 ADSI 列舉會將 Active Directory 服務介面傳回給呼叫端。 為了避免取得新介面指標的額外負荷,ADSI 應用程式應該針對想要操作的物件快取傳回的介面指標。 例如,列舉容器並將名稱填入清單框的Visual Basic應用程式,可以快取與名稱相關聯的介面指標,以供日後使用。 此方法可提供比列舉期間填入清單框更大的效能,並在用戶進行選取時取得新的介面指標。

關於分派標識碼

IDispatch 是由 COM 針對未直接使用 COM 介面的控制器所定義的自動化介面。 透過 IDispatch 存取物件稱為名稱系結或晚期綁定存取,因為它發生在運行時間 (“late”) 並使用屬性和方法的字串名稱來解析參考 (“name” )。 在運行時間,用戶端會將想要呼叫的屬性或方法字串名稱傳遞至 IDispatch::GetIDsOfNames() 方法。 如果物件上有 屬性或方法,則會擷取對應函式的分派標識碼 (dispID)。 dispID 接著會用來透過 IDispatch::Invoke() 執行函式。 在 單一物件所公開介面上使用 IDispatch、屬性和方法會顯示為一般清單。 由於名稱系結存取需要兩個函式呼叫,所以它比直接使用 COM 介面效率低。 當考慮效能時,建議客戶端在物件上使用 ADSI COM 介面。 如果介面符合數據類型和參數傳遞的自動化條件約束,例如 Visual Basic 4.0 等進階自動化控制器可以呼叫其他 COM 介面 和 IDispatch

ADSI 提供者會針對每個 Active Directory 物件動態產生 dispID。 透過 指定物件的 IDispatch::GetIDsOfNames 擷取的 dispID 是 產生的值,但不是物件 IDL 中的值。 IDispatch 用戶必須呼叫 GetIDsOfNames ,才能在運行時間取得有效的 dispID。

類型資訊和類型連結庫

ADSI SDK 提供類型連結庫 Activeds.tlb,可記錄 ADSI 支援的所有標準介面。 提供者必須針對 Activeds.tlb 中找到的所有介面提供類似的類型連結庫,以及提供者元件內實作之介面的任何其他類型數據。

以下是IDL程式代碼範例。

[ object, uuid(IID_IADsXYZ), oleautomation, dual ]
interface IADsXYZ: IDispatch
{
// Read-only properties.
[propget]
HRESULT AReadOnlyProp ([out, retval]BSTR *pbstrAReadOnlyProp);
 
// Read/write properties.
[propget]
HRESULT AReadWriteProp ([out, retval]long *plAReadWriteProp);
[propput]
HRESULT AReadWriteProp ([in]long lAReadWriteProp);
 
// Methods.
HRESULT AMethod ([in]DATE dateInParameter,
[out, retval]BSTR *pbstrReturnValue);
};

執行緒安全性

元件物件模型 (COM) 描述下列三個線程模型。 COM 應用程式會指出使用 CoInitialize CoInitializeEx 函式初始化 COM 連結庫時所使用的模型:

  • 單個線程處理。 單個線程模型假設進程中執行的單一線程,進一步假設進程中的 COM 數據結構不需要存取串行化。
  • Apartment 線程。 COM 物件與建立它的線程相關聯。 對另一個線程上物件的呼叫必須由建立該對象的線程執行。 為了達成此目的,來源線程會叫用用戶端 Proxy,以排列方法呼叫,並透過與目的地線程相關聯的 Win32 消息佇列,將它傳遞給目的地線程中的伺服器存根函式。
  • 免費線程處理。 COM 對象假設為安全線程。 允許多個線程存取進程中沒有任何串行化強制的任何物件。

ADSI 不會假設任何特定的線程模型。 提供者元件的寫入器應該假設免費線程模型,並透過使用重要區段或旗號等同步處理對象,保護其內部數據結構的一致性,以防止線程不安全,也就是未協調的更新。

物件鎖定

ADSI 不會強制或定義物件鎖定配置。 使用鎖定支援存取串行化之命名空間的提供者,可以透過ADI的提供者特定延伸模塊公開基礎鎖定配置。

架構中的屬性名稱

ADSI 會將屬性表示為ADSI架構容器內的屬性物件。 這需要屬性名稱在每個架構容器內是唯一的。 提供者必須確保沒有名稱衝突。

主要介面

當提供者無法識別應傳回為主要介面的介面時, 應該傳回IID_IADs 。 這會透過 IDispatchIADs::Get、IADs::Get、IADs::GetExIADs::P ut 和 IADs::P utEx 方法,提供物件之所有屬性的名稱系結存取權。