屬性儲存體考慮

IPropertyStorage::ReadMultiple 會讀取 rgpspec 陣列中指定的許多屬性,如屬性集中所找到。 只要讀取任何所要求的屬性,擷取不存在之屬性的要求就不是錯誤。 相反地,這必須讓傳回時將該屬性寫入 rgvar[] 陣列VT_EMPTY。 當沒有任何要求的屬性存在時,方法應該傳回S_FALSE,並在每個 PROPVARIANT中設定VT_EMPTY。 如果傳回任何其他錯誤,則不會擷取任何屬性值,而且呼叫端不需要擔心釋放它們。

rgpspec參數是PROPSPEC結構的陣列,它會針對每個屬性指定其屬性識別碼,或如果指派屬性識別碼,則為字串識別碼。 您可以呼叫 IPropertyStorage::WritePropertyNames,將字串對應至屬性識別碼。 不過,屬性識別碼的使用可能比使用字串更有效率。

字串名稱 (PRSPEC_LPWSTR) 要求的屬性會不區分大小寫地對應至屬性識別碼, (識別碼) ,因為它們是在目前屬性集 (中指定,並根據目前的系統地區設定) 。

當屬性類型VT_LPSTR且屬性是從 ANSI 屬性集讀取時,也就是屬性集的字碼頁設定為 Unicode 以外的專案時,屬性的值會使用與屬性集相同的字碼頁。 從 Unicode 屬性集讀取VT_LPSTR屬性時,屬性的值會使用系統的目前預設 ANSI 字碼頁,也就是 從 GetACP 函式傳回的字碼頁。

除了資料流程和儲存體指標的 PROPVARIANT以外, 稱為簡單的 PROPVARIANT。 這些簡單的 PROPVARIANT會依值接收資料,因此 呼叫 IPropertyStorage::ReadMultiple 會提供呼叫端接著擁有的資料複本。 若要建立或更新這些屬性,請呼叫 IPropertyStorage::WriteMultiple

相反地,變體類型VT_STREAM、VT_STREAMED_OBJECT、VT_STORAGE和VT_STORED_OBJECT是非簡單的屬性,因為方法不會提供值,而是擷取指示介面的指標,然後可從中讀取資料。 這些類型允許透過單一屬性儲存大量的資訊。 使用非簡單屬性時發生數個問題。

若要建立這些屬性,如其他屬性一樣,請呼叫 IPropertyStorage::WriteMultiple。 不過,相較于呼叫相同的方法來更新,先呼叫 IPropertyStorage::ReadMultiple 以取得資料流程或儲存體的介面指標,然後使用 IStreamIStorage 方法寫入資料會更有效率。 透過屬性開啟的資料流程或儲存體一律會以直接模式開啟,因此不會引進額外的巢狀交易層級。 不過,根據透過 IPropertySetStorage開啟或建立屬性集的方式,可能會有一個整體上的交易。 此外,在開啟或建立屬性集時指定的存取和共用模式標記會傳遞至屬性型資料流程或儲存體。

屬性型資料流程或儲存指標的存留期,雖然理論上與相關聯的 IPropertyStorageIPropertySetStorage 指標無關,事實上,實際上相依于它們。 透過資料流程或儲存體顯示的資料與擷取其來源之屬性儲存 (物件上的交易相關,就如同支援包含資料流程和儲存子物件的 IStorage) 支援 IStorage) 。 如果父物件上的交易已中止,就無法再存取該物件的現有 IStreamIStorage 指標。 因為 IPropertyStorage是屬性儲存體物件上唯一的介面,所以自主IStreamIStorage指標的實用存留期會受到IPropertyStorage介面的存留期所系結。

實作也必須處理透過相同 IPropertyStorage 介面實例多次要求相同資料流程或儲存體值屬性的情況。 例如,在 COM 複合檔案實作中,開啟將會成功或失敗,視屬性是否已開啟而定。

另一個問題是交易模式中的多個開啟。 結果取決於透過呼叫 IPropertySetStorage 方法所指定的隔離等級, (OpenCreate 方法,透過開啟屬性儲存體時) STGM 旗標。

如果開啟屬性集的呼叫指定讀寫許可權,則一律會以讀寫許可權開啟 IStorageIStream值屬性。 然後,您可以透過這些介面來寫入資料,變更 屬性的值,這是更新這些屬性最有效率的方式。 屬性值本身沒有額外的交易巢狀層級,因此如果屬性儲存物件上有任何) ,變更的範圍會在交易 (下。

儲存體和串流屬性

若要將資料流程或儲存物件寫入屬性集,屬性集必須已建立為非簡單。 如需簡單和非簡單屬性集的詳細資訊,請參閱標題為 屬性集的儲存和串流物件一節。 如rgvar陣列元素的 vt欄位中所指定,下列屬性類型為數據流或儲存類型:VT_STREAM、VT_STORAGE、VT_STREAMED_OBJECT、VT_STORED_OBJECT。

若要將資料流程或儲存物件寫入為非簡單屬性集中的屬性,請呼叫 IPropertyStorage::WriteMultiple。 雖然您也會呼叫此方法來更新簡單屬性,但它不是更新屬性集中資料流程和儲存物件的有效方式。 這是因為透過 對 WriteMultiple 的呼叫更新其中一個屬性會在屬性儲存體物件中建立傳入資料的複本,而 IStorageIStream 指標不會保留超過此呼叫的持續時間。 直接呼叫 IPropertyStorage::ReadMultiple 以取得資料流程或儲存體的介面指標,然後透過 IStreamIStorage 方法寫入資料,通常更有效率。

例如,您可以呼叫 IPropertyStorage::WriteMultiple 來寫入 Null 資料流程或儲存體物件。 然後,實作會在屬性集中建立空白物件。 然後,您可以呼叫 IPropertyStorage::ReadMultiple來存取此物件。 當您完成更新此物件時,您不需要將它寫入屬性集,因為您的更新會直接進入屬性集。

透過屬性開啟的資料流程或儲存體一律會以直接模式開啟,因此不會引進額外的巢狀交易層級。 屬性上仍有一個整體設定的交易。 (例如,如果 IPropertyStorage 是透過呼叫 IPropertySetStorage::Open ,並在 grfmode 參數中設定STGM_TRANSACTED旗標來取得。) 進一步,屬性型資料流程或儲存體會在讀取寫入模式中開啟,如果可能的話,請在屬性集上指定模式;否則,會使用讀取模式。

如先前所述,將資料流程或儲存物件寫入 使用 WriteMultiple 方法設定的屬性時,會建立物件的複本。 在資料流程物件上建立這類複本時,複製作業會從來源的目前搜尋位置開始。 搜尋位置在失敗時未定義,但在成功時則位於資料流程結尾;搜尋指標不會還原至其原始位置。

如果已從具有 ReadMultiple的屬性集讀取資料流程或儲存屬性,仍會保持開啟狀態,而且會建立對相同屬性的 WriteMultiple 後續呼叫, 則 WriteMultiple 作業將會成功。 先前開啟的資料流程或儲存體屬性會處於還原狀態, (所有呼叫都會傳回STG_E_REVERTED錯誤) 。

如果 WriteMultiple 方法在寫入屬性陣列或甚至個別的非簡單屬性時傳回錯誤,則實際寫入的資料量未定義。

參考屬性

如果指定的 PROPVARIANT 結構在其 vt 成員中包含VT_BYREF旗標,則相關聯的屬性是參考屬性。 參考屬性會在將值寫入屬性集之前自動取值。 例如,如果PROPVARIANT結構的vt成員指定類型為 VT_BYREF 的值 |VT_I4,寫入的實際值是VT_I4類型。 後續對 IPropertyStorage::ReadMultiple方法的呼叫會以VT_I4傳回值。 使用參考屬性類似于呼叫 VariantCopyInd 函式。 VariantCopyInd 會釋放目的地變體,並建立來源 VARIANTARG 的複本,並在指定來源時執行必要的間接VT_BYREF。 此函式在需要變體複本時很有用,而且保證它不會VT_BYREF,例如,處理 IDispatch::Invoke實作中的引數時。

給呼叫者的注意事項

建議將屬性集建立為 Unicode,方法是不要在IPropertySetStorage::CreategrfFlags參數中設定 PROPSETFLAG_ANSI 旗標。 也建議您避免使用VT_LPSTR值,並改用VT_LPWSTR值。 當屬性集字碼頁為 Unicode 時,VT_LPSTR字串值會在儲存時轉換成 Unicode,並在擷取時轉換成多位元組字元串值。 當屬性集的字碼頁不是 Unicode 時,屬性名稱、VT_BSTR字串和非簡單屬性值會在儲存時轉換成多位元組字元串,並在擷取時轉換成 Unicode,全部都使用目前的系統 ANSI 字碼頁。

給實施者的注意事項

配置屬性識別碼時,只要它不是 0 或 1 或大於0x80000000,實作就可以選擇屬性識別碼的屬性集中目前未使用的任何值,全部都是保留值。 propidNameFirst參數會在集合內建立屬性識別碼的最小值,而且必須大於 1 且小於0x80000000。 請參閱上述一節。

IPropertyStorage-Compound 檔案實作

IPropertyStorage-NTFS 檔案系統實作

IPropertyStorage-獨立實作