屬性處理常式最佳做法和常見問題

本主題說明如何建立和註冊屬性處理常式,以使用 Windows 屬性系統。

本主題的組織方式如下:

最佳做法

覆寫檔案系統屬性

檔案的某些屬性是由檔案系統資料來源提供,例如:

  • PKEY_FileName
  • PKEY_Extension
  • PKEY_ModifiedTime

一般而言,屬性處理常式無法提供這些屬性的值。 不過,在某些情況下,您可以根據屬性處理常式提供的註冊資訊覆寫這些屬性。 屬性處理常式會將要覆寫的屬性名稱填入HKEY_CLASSES_ROOT\CLSID\{handler clsid}\OverrideFileSystemProperties。 這僅限於下列系統具有知識的一組固定屬性。

下列屬性值支援覆寫:

如需所有 Shell 屬性的完整清單,請參閱 Shell 屬性

重要

只有在索引檔案時,才會使用覆寫的屬性值。 因此,從檔案系統資料來源流覽檔案不會顯示覆寫的值。  

以 XML 為基礎的檔案格式儲存屬性

有兩個基本選項可用來以 XML 為基礎的檔案格式儲存屬性:

  • 根據檔的 XML 架構,使用 XML 元素和屬性來儲存每個屬性。 此方法更「XML 易記」。
  • 將整個屬性存放區序列化為記憶體二進位大型物件, (BLOB) 、將 BLOB 轉換成 base64 編碼字串,然後將該字串儲存在 XML 中。 這是這兩種方法的較簡單方法,可用來簡單提供開啟中繼資料的支援。

例如,某些處理常式可能會結合這些方法,以標準 XML 格式儲存一些重要的值,並將其餘值儲存在 BLOB 中。

計算的屬性

某些屬性衍生自檔案的特定屬性。 例如, System.Image.Dimensions 屬性是由影像檔案中影像的實際維度所決定。 由於屬性處理常式無法變更這類屬性值,因此它們會標示 isInnate="true" 在屬性描述中。 其他屬性是從特定屬性的一部分計算,或藉由匯總多個屬性的值來計算。 由於這些「計算」屬性的更新會建立模棱兩可的方式,因此應該如何變更「來源」值,因此計算屬性應該在屬性描述中標示 isInnate="true" ,或回報為唯讀。 後者的選項是指示處理常式從 IPropertyStoreCapabilities::IsPropertyWritable傳回S_FALSE。

常見問題集

為什麼 Windows 搜尋服務索引子不會載入我的屬性處理常式?

Windows 搜尋服務索引子會以系統服務的形式執行,而且無法載入儲存在使用者設定檔目錄中的 DLL。 如果您要使用 Microsoft Visual Studio 建置和偵錯,它會將 DLL 放在使用者設定檔 (,因此索引子不會載入) 。 若要解決此問題,請將設定檔資料夾外部的 DLL (複製到 C:\Program Files\YourAppName) ,並在該處註冊。

如需開發屬性處理常式以使用 Windows 搜尋索引子的特定指引,請參閱 開發 Windows 搜尋的屬性處理常式

哪些屬性應該可透過 'IPropertyStore::GetCount' 和 'IPropertyStore::GetAt' 列舉方法來探索?

並非所有屬性存放區物件的用戶端都會使用這些方法。 有些用戶端知道他們打算透過 PKEY 名稱) 直接要求 (的屬性,或透過屬性描述清單接收屬性資訊。 屬性探索方法支援數個其他案例。 如果屬性不需要參與這些案例,則不需要列舉。 因此,屬性處理常式可能會針對未透過IPropertyStore::GetCount 和 IPropertyStore::GetAt方法探索的屬性產生非VT_EMPTY值。

不過,如果符合下列任何條件,則應透過這些方法顯示內容:

  • 如果屬性已編制索引,使其可供搜尋: 這表示它包含在 Windows 搜尋屬性存放區中, isColumn = "true" (屬性描述架構) 或可供全文檢索搜尋 (inInvertedIndex = "true") 。 如果沒有這些旗標或沒有屬性描述,類型 「string」 的屬性會自動新增至反向索引,以啟用搜尋。 由於已知屬性清單 (屬性系統中已安裝的屬性描述) 非常龐大, (超過 800 個屬性) ,因此對於在屬性系統中註冊的每個屬性,要求每個屬性處理常式並不實用。 相反地,索引程式會針對索引的每個專案,從屬性處理常式列舉相關屬性,並使用列舉屬性的值來建置全文檢索索引。
  • 如果當專案的屬性集重複時,應該複製屬性: 若要實作「複製屬性集」函式,來源專案會建立應該透過 IPropertyStore::GetCountIPropertyStore::GetAt 方法複製的屬性。 不需要複製或不合理複製的屬性不應該包含在內。
  • 如果屬性值不是空的 (VT_EMPTY) : 空的屬性值不適用於用戶端。 當用戶端嘗試傳回空的屬性值時,會傳回VT_EMPTY的值。 因此,不應該列舉具有空白值的屬性。
  • 如果在叫用「移除屬性」函式時應移除屬性: 這項功能存在以保護隱私權;它會透過列舉來探索屬性處理常式中的所有值,並移除使用者選取的每個值以供移除。

注意

如果處理常式支援固定架構 (且未開啟中繼資料) ,則列舉屬性不會傳達特定屬性處理常式所支援的屬性集。 相反地,這類處理常式應該記載它們支援的一組屬性。

 

如何?知道哪些檔案格式支援開啟中繼資料?

For information about support for open metadata, see "File Types that Support Open Metadata" in File Types.

可以使用屬性處理常式來儲存VT_Null值嗎?

不會。 VT_Null值將會在呼叫IPropertyStore::GetValue 和 IPropertyStore::SetValue時轉換成VT_EMPTY。

'PropVariantChangeType' 函式支援哪些日期字串格式?

一般而言,表示日期/時間值的屬性應該使用VT_FILETIME來表示。 不過,許多資料來源會以字串形式提供這項資訊。 PropVariantChangeType協助程式 API 支援將某些字串日期格式強制轉換成FILETIME值,如下表所示。

格式 Windows Vista、Windows XP 和 Microsoft Windows 桌面搜尋 (WDS) Windows 7 備註
yyyy/mm/dd:hh:mm:ss.uuu Yes Yes Utc;y=year、m=month、d=date、h=hours (24 小時制) 、m=minutes、s=seconds、u=microseconds
yyyy-mm-ddThh:mm:ssZ No Yes ISO8601 格式規格UTC (以 'Z' 時區指標表示) ;y=year、m=month、d=date、h=hours (24 小時制) 、m=minutes、s=seconds;'T' 是時間部分的分隔符號。

是否可以建立唯讀屬性處理常式?

是的。 某些屬性處理常式實作不支援寫入屬性值。 這些屬性處理常式應該會在對 傳遞 STGM_READWRITE 的 IInitializeXXX::Initialize 呼叫時,或在 對 IPropertyStore::SetValue的任何呼叫上傳回STGM_E_ACCESSDENIED。

在呼叫 IPropertyStore::SetValue時,在STGM_READ模式中開啟的所有屬性處理常式都應該傳回STGM_E_ACCESSDENIED。

屬性處理常式是否可以將屬性視為唯讀,即使架構指出屬性是可寫入的嗎?

是的。 在架構系統中,屬性會批註為唯讀 (,包括具有 isInnate = "true") 或讀取/寫入的屬性。 不支援撰寫特定屬性的屬性處理常式,架構應該可寫入,應該實作 IPropertyStoreCapabilities ,並在呼叫 IPropertyStoreCapabilities::IsPropertyWritable 時傳回S_FALSE。 這表示在這個處理常式和這個檔案的內容中,屬性無法寫入。

注意

無法進行反向動作。 您無法讓屬性處理常式寫入架構中標示為唯讀的屬性