建立 Shell 擴充功能處理常式

Shell 的功能可以使用登錄專案和.ini檔案來擴充。 雖然擴充殼層的這個方法很簡單,而且適合許多用途,但有限。 例如,如果您使用登錄來指定檔案類型的自訂圖示,該類型的每個檔案都會顯示相同的圖示。 使用登錄擴充殼層並不允許您變更相同類型不同檔案的圖示。 Shell 的其他層面,例如 屬性 屬性工作表,可在檔案按一下滑鼠右鍵時顯示,完全無法透過登錄修改。

擴充殼層更強大且彈性的方法,就是實 作殼層擴充處理常式。 這些處理常式可以針對 Shell 可執行檔各種動作來實作。 在採取動作之前,Shell 會查詢擴充處理常式,讓您有機會修改動作。 常見的範例是快捷方式功能表延伸模組處理常式。 如果針對檔案類型實作其中一個,每當其中一個檔案按一下滑鼠右鍵時,就會查詢它。 處理常式接著可以逐一檔案指定其他功能表項目,而不是針對整個檔案類型設定相同的功能表項目。

本檔討論如何實作延伸模組處理常式,讓您修改各種殼層動作。 下列處理常式與特定檔案類型相關聯,可讓您逐一指定檔案:

處理常式 描述
快捷方式功能表處理常式 在顯示檔案的快捷方式功能表之前呼叫。 它可讓您依檔案將專案新增至快捷方式功能表。
資料處理程式 在 dragShell 物件上執行拖放作業時呼叫。 它可讓您將其他剪貼簿格式提供給置放目標。
卸載處理常式 在檔案上拖曳或卸載資料物件時呼叫。 它可讓您將檔案設為置放目標。
圖示處理常式 在檔案的圖示顯示之前呼叫。 它可讓您以檔案為基礎的自訂圖示取代檔案的預設圖示。
屬性工作表處理常式 在物件的 Properties 屬性 表顯示之前呼叫。 它可讓您新增或取代頁面。
縮圖影像處理常式 提供影像來表示專案。
資訊提示處理常式 當使用者將滑鼠指標停留在 物件上方時,提供快顯文字。
元資料處理程式 提供儲存在檔案中) 中繼資料 (中繼資料的讀取和寫入存取權。 這可用來擴充 [詳細資料] 檢視、資訊提示、屬性頁和群組功能。

 

其他處理常式不會與特定檔案類型相關聯,但在某些 Shell 作業之前呼叫:

處理常式 描述
資料行處理常式 由 Windows 檔案總管呼叫,再顯示資料夾的 [詳細資料] 檢視。 它可讓您將自訂資料行新增至 [詳細資料] 檢視。
複製勾點處理常式 當資料夾或印表機物件即將移動、複製、刪除或重新命名時呼叫。 它可讓您核准或核准作業。
拖放功能處理常式 使用滑鼠右鍵拖曳檔案時呼叫。 它可讓您修改顯示的快捷方式功能表。
圖示重迭處理常式 在檔案的圖示顯示之前呼叫。 它可讓您指定檔案圖示的重迭。
搜尋處理常式 呼叫 以啟動搜尋引擎。 它可讓您實作可從 [ 開始 ] 功能表或 Windows 檔案總管存取的自訂搜尋引擎。

 

上述各節涵蓋如何實作特定擴充處理常式的詳細資料。 本檔的其餘部分涵蓋所有 Shell 擴充處理常式通用的一些實作問題。

實作殼層擴充處理常式

Shell 擴充處理常式物件的大部分實作取決於其類型。 不過,有一些常見的元素。 本節討論所有 Shell 延伸模組處理常式所共用實作的各個層面。

許多殼層擴充處理常式都是內建元件物件模型, (COM) 物件。 它們必須指派 GUID 並註冊,如註冊殼層延伸模組處理常式中所述。 它們會實作為 DLL,而且必須匯出下列標準函式:

  • DllMain。 DLL 的標準進入點。
  • DllGetClassObject。 公開物件的類別處理站。
  • DllCanUnloadNow。 COM 會呼叫此函式,以判斷物件是否為任何用戶端提供服務。 如果沒有,系統可以卸載 DLL 並釋放相關聯的記憶體。

如同所有 COM 物件,Shell 擴充處理常式必須實作 IUnknown 介面和 類別處理站。 大部分的擴充處理常式也必須在 Windows XP 或更早版本中實作 IPersistFileIShellExtInit 介面。 這些已由 Windows Vista 中的 IInitializeWithStreamIInitializeWithItemIInitializeWithFile 取代。 Shell 會使用這些介面來初始化處理常式。

IPersistFile介面必須由下列專案實作:

  • 資料處理程式
  • 卸載處理常式

在過去,也需要圖示處理常式來實作 IPersistFile,但這已不再成立。 對於圖示處理常式, IPersistFile 現在是選擇性的,而 IInitializeWithItem 等其他介面是慣用的。

IShellExtInit介面必須由下列專案實作:

  • 快捷方式功能表處理常式
  • 拖放處理常式
  • 屬性工作表處理常式

實作 IPersistFile

IPersistFile介面旨在允許從磁片檔案載入或儲存物件。 除了IUnknown之外,它還有六個方法、五個自己的方法,以及繼承自IPersistGetClassID方法。 使用殼層擴充功能時, IPersist 只會用來初始化 Shell 延伸模組處理常式物件。 因為通常不需要讀取或寫入磁片,所以只有 GetClassIDLoad 方法需要非ken 實作。

Shell 會先呼叫 GetClassID ,函式會傳回擴充處理常式物件的 CLSID) (類別識別碼。 殼層接著會呼叫 Load 並傳入兩個值。 第一個 pszFileName是 Unicode 字串,其名稱為 Shell 即將運作的檔案或資料夾。 第二個是 dwMode,表示檔案存取模式。 因為通常不需要存取檔案, 所以 dwMode 通常是零。 方法會視需要儲存這些值,以供稍後參考。

下列程式碼片段說明一般 Shell 延伸模組處理常式如何實作 GetClassIDLoad 方法。 其設計目的是要處理 ANSI 或 Unicode。 CLSID_SampleExtHandler是擴充處理常式物件的 GUID,而 CSampleExtHandler 是用來實作介面的類別名稱。 m_szFileNamem_dwMode變數是用來儲存檔案名和存取旗標的私人變數。

wchar_t m_szFileName[MAX_PATH];    // The file name
DWORD m_dwMode;                  // The file access mode

CSampleExtHandler::GetClassID(CLSID *pCLSID)
{
    *pCLSID = CLSID_SampleExtHandler;
}

CSampleExtHandler::Load(PCWSTR pszFile, DWORD dwMode)
{
    m_dwMode = dwMode;
    return StringCchCopy(_szFileName, ARRAYSIZE(m_szFileName), pszFile);
}

實作 IShellExtInit

除了IUnknown之外,IShellExtInit介面只有一個方法IShellExtInit::Initialize。 方法有三個參數,Shell 可用來傳入各種類型的資訊。 傳入的值取決於處理常式的類型,有些值可以設定為 Null

  • pIDFolder 會保存專案識別碼清單的資料夾指標, (PIDL) 。 如果是屬性工作表延伸模組,則為 Null。 針對快捷方式功能表延伸模組,它是資料夾的 PIDL,其中包含要顯示其快捷方式功能表的專案。 對於非預設拖放處理常式,它是目的檔案夾的 PIDL。
  • pDataObject 會保存資料物件的 IDataObject 介面指標。 資料物件會以 CF_HDROP 格式保存一或多個檔案名。
  • hRegKey 會保存檔案物件或資料夾類型的登錄機碼。

IShellExtInit::Initialize方法會視需要儲存檔案名、IDataObject指標和登錄機碼,以供稍後使用。 下列程式碼片段說明 IShellExtInit::Initialize的實作。 為了簡單起見,此範例假設資料物件只包含單一檔案。 一般而言,它可能包含需要擷取的多個檔案。

LPCITEMIDLIST  m_pIDFolder;           //The folder's PIDL
wchar_t        m_szFile[MAX_PATH];    //The file name
IDataObject   *m_pDataObj;            //The IDataObject pointer
HKEY           m_hRegKey;             //The file or folder's registry key

STDMETHODIMP CShellExt::Initialize(LPCITEMIDLIST pIDFolder, 
                                   IDataObject *pDataObj, 
                                   HKEY hRegKey) 
{ 
    // If Initialize has already been called, release the old PIDL
    ILFree(m_pIDFolder);
    m_pIDFolder = nullptr;

    // Store the new PIDL.
    if (pIDFolder)
    {
        m_pIDFolder = ILClone(pIDFolder);
    }
    
    // If Initialize has already been called, release the old
    // IDataObject pointer.
    if (m_pDataObj)
    { 
        m_pDataObj->Release(); 
    }
     
    // If a data object pointer was passed in, save it and
    // extract the file name. 
    if (pDataObj) 
    { 
        m_pDataObj = pDataObj; 
        pDataObj->AddRef(); 
      
        STGMEDIUM   medium;
        FORMATETC   fe = {CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL};
        UINT        uCount;

        if (SUCCEEDED(m_pDataObj->GetData(&fe, &medium)))
        {
            // Get the count of files dropped.
            uCount = DragQueryFile((HDROP)medium.hGlobal, (UINT)-1, NULL, 0);

            // Get the first file name from the CF_HDROP.
            if (uCount)
                DragQueryFile((HDROP)medium.hGlobal, 0, m_szFile, 
                              sizeof(m_szFile)/sizeof(TCHAR));

            ReleaseStgMedium(&medium);
        }
    }

    // Duplicate the registry handle. 
    if (hRegKey) 
        RegOpenKeyEx(hRegKey, nullptr, 0L, MAXIMUM_ALLOWED, &m_hRegKey); 
    return S_OK; 
}

CSampleExtHandler 是用來實作介面的類別名稱。 m_pIDFolderm_pDataObjectm_szFileNamem_hRegKey變數是用來儲存傳入資訊的私用變數。 為了簡單起見,此範例假設資料物件只會保留一個檔案名。 從資料物件擷取 FORMATETC 結構之後, DragQueryFile 會用來從 FORMATETC 結構的 medium.hGlobal 成員擷取檔案名。 如果傳入登錄機碼,此方法會使用 RegOpenKeyEx 開啟機碼,並將控制碼指派給 m_hRegKey

資訊提示自訂

有兩種方式可以自訂資訊提示:

  • 實作支援 IQueryInfo 的物件,然後在登錄中的適當子機碼下註冊該物件, (請參閱下方的 註冊殼層擴充處理常式) 。
  • 指定要顯示之特定檔案屬性的固定字串或清單。

若要顯示命名空間延伸模組的固定字串,請在命名空間延伸模組的{CLSID}索引鍵中建立名為 InfoTip 的專案。 將該專案的值設定為您想要顯示的常值字串,如本範例所示,或指定該資源內的資源和索引的間接字串, (以供當地語系化之用) 。

HKEY_CLASSES_ROOT
   CLSID
      {CLSID}
         InfoTip = InfoTip string for your namespace extension

若要顯示檔案類型的固定字串,請在該檔案類型的ProgID索引鍵中建立名為 InfoTip 的專案。 將該專案的值設定為您想要顯示的常值字串,或指定該資源內資源與索引的間接字串,以 (進行當地語系化,) ,如本範例所示。

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = Resource.dll, 3

如果您想要 Shell 在特定檔案類型的資訊提示中顯示特定檔案屬性,請在該檔案類型的ProgID機碼中建立名為 InfoTip 的專案。 將該專案的值設定為標準屬性名稱的分號分隔清單、格式識別碼 (FMTID) /property identifier (PID) 組,或兩者。 這個值必須以 「prop:」 開頭,才能將其識別為屬性清單字串。 如果您省略 「prop:」,此值會顯示為常值字串,並如下所示。

在下列範例中, propname 是標準屬性名稱, (例如 System.Date) 和 {fmtid},pidFMTID/PID 配對。

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = prop:propname;propname;{fmtid},pid;{fmtid},pid

您可以使用下列屬性名稱:

屬性名稱 描述 擷取自
作者 檔的作者 PIDSI_AUTHOR
標題 檔的標題 PIDSI_TITLE
主旨 主旨摘要 PIDSI_SUBJECT
註解 檔批註 PIDSI_COMMENT 或資料夾/驅動程式屬性
PageCount 頁面數目 PIDSI_PAGECOUNT
名稱 易記名稱 標準資料夾檢視
OriginalLocation 原始檔案的位置 公事包資料夾和回收站資料夾
DateDeleted 刪除日期檔案 回收站資料夾
類型 檔案類型 標準資料夾詳細資料檢視
大小 檔案大小 標準資料夾詳細資料檢視
SyncCopyIn 與 OriginalLocation 相同 與 OriginalLocation 相同
修改日期 上次修改日期 標準資料夾詳細資料檢視
建立時間 建立日期 標準資料夾詳細資料檢視
存取方式 上次存取的日期 標準資料夾詳細資料檢視
InFolder 包含檔案的目錄 檔搜尋結果
排名 搜尋比對的品質 檔搜尋結果
FreeSpace 可用的儲存空間 磁碟機
NumberOfVisits 瀏覽次數 我的最愛資料夾
屬性 檔案屬性 標準資料夾詳細資料檢視
公司 公司名稱 PIDDSI_COMPANY
類別 檔類別 PIDDSI_CATEGORY
著作權 媒體著作權 PIDMSI_COPYRIGHT
HTMLInfoTipFile HTML 資訊提示檔案 資料夾Desktop.ini檔案

 

使用殼層延伸模組處理常式增強 Windows 搜尋

殼層延伸模組處理常式可用來增強 Windows 搜尋通訊協定處理常式所提供的使用者體驗。 若要啟用這類增強功能,支援的 Shell 延伸模組處理常式必須設計成與搜尋通訊協定處理常式整合為數據源。 如需如何透過與 Shell 擴充功能處理常式整合來增強 Windows 搜尋通訊協定處理常式的詳細資訊,請參閱 新增圖示、預覽和快捷方式功能表。 如需 Windows 搜尋通訊協定處理常式的詳細資訊,請參閱 開發通訊協定處理常式

註冊殼層延伸模組處理常式

Shell 延伸模組處理常式物件必須先註冊,Shell 才能使用它。 本節是如何註冊 Shell 延伸模組處理常式的一般討論。

每當建立或變更 Shell 擴充處理常式時,請務必通知系統您已使用 SHChangeNotify進行變更,並指定 SHCNE_ASSOCCHANGED 事件。 如果您未呼叫 SHChangeNotify,在系統重新開機之前,可能無法辨識變更。

如同所有 COM 物件,您必須使用 UUIDGEN.exe 之類的工具來建立處理常式的 GUID。 在HKEY_CLASSES_ROOT\CLSID底下建立金鑰,其名稱為 GUID 的字串形式。 因為 Shell 擴充處理常式是同進程伺服器,所以您必須在 GUID 機碼下建立 InProcServer32 機碼,並將預設值設定為處理常式 DLL 的路徑。 使用 Apartment 執行緒模型。

每當 Shell 採取可能涉及殼層延伸模組處理常式的動作時,它會檢查適當的登錄機碼。 註冊擴充處理常式的索引鍵,因此會在呼叫時控制它。 例如,當 Shell 顯示 檔案類型成員的快捷方式功能表時,呼叫快顯功能表處理常式是常見的做法。 在此情況下,處理常式必須在檔案類型的 ProgID 機碼下註冊。

處理常式名稱

若要啟用 Shell 延伸模組處理常式,請使用處理程式子機碼名稱建立子機碼, (請參閱下列) 在) 檔案類型的ProgID (子機碼底下,或預先定義殼層物件的 Shell物件類型名稱 () 。

例如,如果您想要註冊 MyProgram.1 的快捷方式功能表延伸處理常式,首先會建立下列子機碼:

HKEY_CLASSES_ROOT
   MyProgram.1
      ShellEx
         ContextMenuHandlers

針對下列處理常式,請在 「Handler Subkey name」 機碼底下建立子機碼,其名稱為 Shell 擴充功能的 CLSID 字串版本。 您可以藉由建立多個子機碼,在處理常式子機碼名稱索引鍵下註冊多個延伸模組。

處理常式 介面 處理常式子機碼名稱
快捷方式功能表處理常式 ICoNtextMenu CoNtextMenuHandlers
Copyhook 處理常式 ICopyHook CopyHookHandlers
拖放功能處理常式 ICoNtextMenu DragDropHandlers
屬性工作表處理常式 IShellPropSheetExt PropertySheetHandlers
Windows Vista) 中已淘汰的資料行提供者處理常式 ( IColumnProvider ColumnHandlers

 

針對下列處理常式,「處理常式子機碼名稱」索引鍵的預設值是 Shell 擴充功能的 CLSID 字串版本。 這些處理常式只能註冊一個擴充功能。

處理常式 介面 處理常式子機碼名稱
資料處理程式 IDataObject DataHandler
置放處理常式 IDropTarget DropHandler
圖示處理常式 IExtractIconA/W IconHandler
影像處理常式 IExtractImage {BB2E617C-0920-11d1-9A0B-00C04FC2D6C1}
縮圖影像處理常式 IThumbnailProvider {E357FCCD-A995-4576-B01F-234630154E96}
資訊提示處理常式 IQueryInfo {00021500-0000-0000-C000-000000000046}
ANSI ) (殼層連結 IShellLinkA {000214EE-0000-0000-C000-00000000046}
殼層連結 (UNICODE) IShellLinkW {000214F9-0000-0000-C000-000000000046}
結構化儲存體 IStorage {0000000B-0000-0000-C000-000000000046}
中繼資料 IPropertyStore PropertyHandler
中繼資料 Windows Vista) 中已被取代的 IPropertySetStorage ( PropertyHandler
釘選到 [開始] 功能表 IStartMenuPinnedList {a2a9545d-a0c2-42b4-9708-a0b2badd77c8}
釘選到工作列 {90AA3A4E-1CBA-4233-B8BB-535773D48449}

 

指定用來將 [釘選到開始] 功能表[釘選到工作列] 的子機碼,只需要包含 IsShortCut 專案的檔案類型。

Windows Vista 已移除資料行提供者處理常式的支援。 此外,從 Windows Vista 開始, IPropertySetStorage 已被取代為 IPropertyStore

雖然 IExtractImage 仍受到支援,但 Windows Vista 和更新版本偏好使用 IThumbnailProvider

預先定義的殼層物件

Shell 會在 HKEY_CLASSES_ROOT 下定義其他物件,其可透過與檔案類型相同的方式進行擴充。 例如,若要新增所有檔案的屬性工作表處理常式,您可以在 PropertySheetHandlers 索引鍵下註冊。

HKEY_CLASSES_ROOT
   *
      shellex
         PropertySheetHandlers

下表提供可註冊擴充處理常式HKEY_CLASSES_ROOT的各種子機碼。 請注意,許多擴充處理常式都無法在所有列出的子機碼下註冊。 如需詳細資訊,請參閱特定處理常式的檔。

子機碼 Description 可能的處理常式 版本
* 所有檔案 快捷方式功能表、屬性工作表、動詞 (請參閱下列) 全部
AllFileSystemObjects 所有檔案和檔案資料夾 快顯功能表、屬性工作表、動詞 4.71
資料夾 全部資料夾 快顯功能表、屬性工作表、動詞 全部
目錄 資料夾 快顯功能表、屬性工作表、動詞 全部
Directory\Background 檔案資料夾背景 僅限快捷方式功能表 4.71
磁碟機 MyComputer 中的所有磁片磁碟機,例如 「C:\」 快顯功能表、屬性工作表、動詞 全部
Network [我的網路位置] 底下的整個網路 () 快顯功能表、屬性工作表、動詞 全部
Network\Type\# 類型的所有物件 # (請參閱下方) 快顯功能表、屬性工作表、動詞 4.71
NetShare 所有網路共用 快顯功能表、屬性工作表、動詞 4.71
NetServer 所有網路伺服器 快顯功能表、屬性工作表、動詞 4.71
network_provider_name 網路提供者 「network_provider_name」提供的所有物件 快顯功能表、屬性工作表、動詞 全部
印表機 所有印表機 快顯功能表、屬性工作表 全部
AudioCD CD 磁片磁碟機中的音訊 CD 僅限動詞 全部
Dvd DVD 磁片磁碟機 (Windows 2000) 快顯功能表、屬性工作表、動詞 4.71

 

注意:

  • 檔案資料夾背景快捷方式功能表是透過在檔案資料夾內按一下滑鼠右鍵來存取,但不能在任何資料夾的內容上存取。
  • 「Verbs」 是HKEY_CLASSES_ROOT子機碼殼層\動詞\\ 註冊的特殊命令。
  • 對於[網路\類型\# ],「#」 是十進位中的網路提供者類型代碼。 網路提供者類型代碼是網路類型的高字。 在 Winnetwk.h 標頭檔中會提供網路類型清單, (WNNC_NET_* 值) 。 例如,WNNC_NET_SHIVA 0x00330000,因此對應的類型索引鍵會HKEY_CLASSES_ROOT\網路\類型\51
  • network_provider_name」 是 WNetGetProviderName所指定的網路提供者名稱,其空格會轉換成底線。 例如,如果已安裝 Microsoft 網路提供者,則其提供者名稱為 「Microsoft Windows Network」,而對應的network_provider_name則Microsoft_Windows_Network

延伸模組處理常式註冊的範例

若要啟用特定處理常式,請使用處理程式名稱,在擴充處理常式類型索引鍵下建立子機碼。 Shell 不會使用處理程式的名稱,但必須與該類型子機碼下所有其他名稱不同。 將名稱子機碼的預設值設定為處理常式 GUID 的字串形式。

下列範例說明使用範例 .myp 檔案類型啟用快捷方式功能表和屬性工作表副檔名處理常式的登錄專案:

HKEY_CLASSES_ROOT
   .myp
      (Default) = MyProgram.1
   CLSID
      {00000000-1111-2222-3333-444444444444}
         InProcServer32
            (Default) = C:\MyDir\MyCommand.dll
            ThreadingModel = Apartment
      {11111111-2222-3333-4444-555555555555}
         InProcServer32
            (Default) = C:\MyDir\MyPropSheet.dll
            ThreadingModel = Apartment
   MyProgram.1
      (Default) = MyProgram Application
      Shellex
         ContextMenuHandler
            MyCommand
               (Default) = {00000000-1111-2222-3333-444444444444}
         PropertySheetHandlers
            MyPropSheet
               (Default) = {11111111-2222-3333-4444-555555555555}

本節中討論的註冊程式必須遵循所有 Windows 系統。

實作In-Process延伸模組的指引