Создание обработчиков расширений оболочки

Возможности оболочки можно расширить с помощью записей реестра и .ini файлов. Хотя этот подход к расширению оболочки прост и подходит для многих целей, он ограничен. Например, если вы используете реестр для указания пользовательского значка для типа файла, для каждого файла этого типа будет отображаться один и тот же значок. Расширение оболочки с помощью реестра не позволяет изменять значок для разных файлов одного типа. Другие аспекты оболочки, такие как страница свойств Свойства , которая может отображаться при щелчке правой кнопкой мыши по файлу, не могут быть изменены с помощью реестра.

Более эффективный и гибкий подход к расширению оболочки заключается в реализации обработчиков расширений оболочки. Эти обработчики можно реализовать для различных действий, которые может выполнять оболочка. Перед выполнением действия оболочка запрашивает обработчик расширения, предоставляя ему возможность изменить действие. Распространенным примером является обработчик расширения контекстного меню. Если он реализован для типа файла, он будет запрашиваться каждый раз, когда один из файлов щелкается правой кнопкой мыши. Затем обработчик может указать дополнительные пункты меню для каждого файла, а не иметь одинаковый набор для всего типа файла.

В этом документе описывается, как реализовать обработчики расширений, которые позволяют изменять различные действия оболочки. Следующие обработчики связаны с определенным типом файлов и позволяют указать по файлам:

Обработчик Описание
Обработчик контекстного меню Вызывается перед отображением контекстного меню файла. Она позволяет добавлять элементы в контекстное меню по файлам.
Обработчик данных Вызывается при выполнении операции перетаскивания с объектами dragShell. Это позволяет предоставить дополнительные форматы буфера обмена для целевого объекта удаления.
Обработчик удаления Вызывается при перетаскивании объекта данных в файл или при его перетаскивании в файл. Это позволяет преобразовать файл в целевой объект удаления.
Обработчик значков Вызывается перед отображением значка файла. Это позволяет заменить значок файла по умолчанию на пользовательский значок для каждого файла.
Обработчик страницы свойств Вызывается перед отображением страницы свойств свойства объекта. Он позволяет добавлять или заменять страницы.
Обработчик эскизов изображений Предоставляет изображение для представления элемента.
Обработчик подсказок Предоставляет всплывющий текст, когда пользователь навевает указатель мыши на объект.
Обработчик метаданных Предоставляет доступ на чтение и запись к метаданным (свойствам), хранящимся в файле. Его можно использовать для расширения представления сведений, подсказок, страницы свойств и функций группирования.

 

Другие обработчики не связаны с определенным типом файлов, но вызываются перед некоторыми операциями оболочки:

Обработчик Описание
Обработчик столбцов Вызывается Windows Обозреватель перед отображением представления сведений о папке. Она позволяет добавлять настраиваемые столбцы в представление Сведений.
Обработчик перехватчика копирования Вызывается при перемещении, копировании, удалении или переименовании объекта папки или принтера. Это позволяет утвердить операцию или наказать вето.
Обработчик действия перетаскивания Вызывается при перетаскивании файла с помощью правой кнопки мыши. Он позволяет изменить отображаемое контекстное меню.
Обработчик наложения значков Вызывается перед отображением значка файла. Это позволяет указать наложение для значка файла.
Обработчик поиска Вызывается для запуска поисковой системы. Она позволяет реализовать пользовательскую поисковую систему, доступную из меню "Пуск" или Обозреватель Windows.

 

Сведения о том, как реализовать определенные обработчики расширений, рассматриваются в разделах, перечисленных выше. В оставшейся части этого документа рассматриваются некоторые проблемы реализации, которые являются общими для всех обработчиков расширений оболочки.

Реализация обработчиков расширений оболочки

Большая часть реализации объекта обработчика расширения оболочки зависит от его типа. Однако существуют некоторые общие элементы. В этом разделе рассматриваются аспекты реализации, общие для всех обработчиков расширений оболочки.

Многие обработчики расширений оболочки являются внутрипроцессными объектами модели COM. Им необходимо присвоить идентификатор GUID и зарегистрировать их, как описано в разделе Регистрация обработчиков расширений оболочки. Они реализуются как библиотеки DLL и должны экспортировать следующие стандартные функции:

  • DllMain. Стандартная точка входа в библиотеку DLL.
  • DllGetClassObject. Предоставляет фабрику классов объекта.
  • DllCanUnloadNow. COM вызывает эту функцию, чтобы определить, обслуживает ли объект какие-либо клиенты. В противном случае система может выгрузить библиотеку DLL и освободить связанную память.

Как и все COM-объекты, обработчики расширений оболочки должны реализовывать интерфейс IUnknown и фабрику классов. Большинство обработчиков расширений также должны реализовывать интерфейс IPersistFile или IShellExtInit в Windows XP или более ранней версии. Они были заменены IInitializeWithStream, IInitializeWithItem и IInitializeWithFile в Windows Vista. Оболочка использует эти интерфейсы для инициализации обработчика.

Интерфейс IPersistFile должен быть реализован следующим образом:

  • Обработчики данных
  • Удаление обработчиков

В прошлом обработчики значков также требовались для реализации IPersistFile, но это уже не так. Для обработчиков значков IPersistFile теперь является необязательным, а другие интерфейсы, такие как IInitializeWithItem , являются предпочтительными.

Интерфейс IShellExtInit должен быть реализован следующим образом:

  • Обработчики контекстного меню
  • Обработчики перетаскивания
  • Обработчики страниц свойств

Реализация IPersistFile

Интерфейс IPersistFile предназначен для загрузки объекта из файла диска или его сохранения в файле диска. В ней есть шесть методов, помимо IUnknown, пять собственных, и метод GetClassID , который он наследует от IPersist. При использовании расширений Оболочки IPersist используется только для инициализации объекта обработчика расширения Оболочки. Так как обычно нет необходимости считывать данные с диска или записывать их на диск, только методы GetClassID и Load требуют реализации nontoken.

Оболочка сначала вызывает GetClassID , а функция возвращает идентификатор класса (CLSID) объекта обработчика расширения. Затем оболочка вызывает Load и передает два значения. Первый, pszFileName, представляет собой строку Юникода с именем файла или папки, с которой будет работать оболочка. Второй — dwMode, который указывает режим доступа к файлу. Так как доступ к файлам обычно не требуется, dwMode обычно равен нулю. Метод сохраняет эти значения по мере необходимости для последующего использования.

В следующем фрагменте кода показано, как типичный обработчик расширения оболочки реализует методы GetClassID и Load . Он предназначен для обработки ANSI или Юникода. CLSID_SampleExtHandler — guid объекта обработчика расширения, а CSampleExtHandler — имя класса, используемого для реализации интерфейса. Переменные m_szFileName и m_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

Интерфейс IShellExtInit содержит только один метод , IShellExtInit::Initialize, в дополнение к IUnknown. Метод имеет три параметра, которые оболочка может использовать для передачи информации различных типов. Передаваемые значения зависят от типа обработчика, а для некоторых можно задать значение 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_pIDFolder, m_pDataObject, m_szFileName и m_hRegKey являются частными переменными, используемыми для хранения передаваемых сведений. Для простоты в этом примере предполагается, что объект данных будет хранить только одно имя файла. После извлечения структуры FORMATETC из объекта данных dragQueryFile используется для извлечения имени файла из элемента medium.hGlobal структуры FORMATETC. Если передается раздел реестра, метод использует RegOpenKeyEx для открытия ключа и назначает дескриптор m_hRegKey.

Настройка подсказки

Существует два способа настройки подсказок:

Чтобы отобразить фиксированную строку для расширения пространства имен, создайте запись с именем InfoTip в ключе {CLSID} расширения пространства имен. Задайте для этой записи значение либо литеральной строки, которую вы хотите отобразить, как показано в этом примере, либо непрямой строкой, указывающей ресурс и индекс внутри этого ресурса (в целях локализации).

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

Чтобы отобразить фиксированную строку для типа файла, создайте запись с именем InfoTip в ключе ProgID этого типа файла. Задайте значение этой записи как литеральную строку, которую требуется отобразить, или непрямую строку, указывающую ресурс и индекс в этом ресурсе (в целях локализации), как показано в этом примере.

HKEY_CLASSES_ROOT
   ProgID
      InfoTip = Resource.dll, 3

Если вы хотите, чтобы оболочка отображала определенные свойства файла в подсказке для определенного типа файла, создайте запись с именем InfoTip в ключе ProgID для этого типа файлов. Задайте значение этой записи в виде разделенного точкой с запятой списка канонических имен свойств, пар идентификатора формата (FMTID)/идентификатора свойства (PID) или и того, и другого. Это значение должно начинаться с "prop:", чтобы определить его как строку списка свойств. Если опустить "prop:", значение будет рассматриваться как литеральное значение и отображаться как таковое.

В следующем примере propname является каноническим именем свойства (например, System.Date), а {fmtid}, pid — парой FMTID/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 Количество посещений Папка "Избранное"
Атрибуты Атрибуты файла Стандартное представление сведений о папке
Company Название организации PIDDSI_COMPANY
Категория Категория документа PIDDSI_CATEGORY
Авторские права Авторские права на сми PIDMSI_COPYRIGHT
HTMLInfoTipFile HTML InfoTip-файл файл Desktop.ini для папки

 

Улучшение Поиска Windows с помощью обработчиков расширений оболочки

Обработчики расширений оболочки можно использовать для улучшения взаимодействия с пользователем, предоставляемого обработчиком протокола Windows Search. Для включения таких улучшений необходимо спроектировать вспомогательный обработчик расширений оболочки для интеграции с обработчиком протокола поиска в качестве источника данных. Сведения о том, как улучшить обработчик протокола Windows Search за счет интеграции с обработчиком расширения оболочки, см. в разделе Добавление значков, предварительных просмотров и контекстных меню. Дополнительные сведения об обработчиках протоколов Windows Search см. в разделе Разработка обработчиков протоколов.

Регистрация обработчиков расширений оболочки

Объект обработчика расширения оболочки должен быть зарегистрирован, прежде чем оболочка сможет его использовать. В этом разделе описано, как зарегистрировать обработчик расширения оболочки.

При создании или изменении обработчика расширения оболочки важно уведомлять систему о том, что вы внесли изменения с помощью SHChangeNotify, указав событие SHCNE_ASSOCCHANGED . Если вы не вызываете SHChangeNotify, изменение может быть не распознано до перезагрузки системы.

Как и для всех COM-объектов, необходимо создать GUID для обработчика с помощью такого средства, как UUIDGEN.exe. Создайте ключ в HKEY_CLASSES_ROOT\CLSID , имя которого является строковой формой GUID. Так как обработчики расширений оболочки являются внутрипроцессными серверами, необходимо создать ключ InProcServer32 в ключе GUID со значением по умолчанию, равным пути библиотеки DLL обработчика. Используйте модель потоков Apartment.

Каждый раз, когда оболочка выполняет действие, которое может включать обработчик расширения оболочки, она проверяет соответствующий раздел реестра. Таким образом, ключ, с помощью которого регистрируется обработчик расширения, определяет, когда он будет вызываться. Например, обычно используется обработчик контекстного меню, вызываемый при отображении контекстного меню для элемента типа файла. В этом случае обработчик должен быть зарегистрирован под ключом ProgID типа файла.

Имена обработчиков

Чтобы включить обработчик расширения оболочки, создайте подраздел с именем подраздела обработчика (см. ниже) в подразделе ShellExлибо ProgID (для типов файлов), либо имя типа объекта оболочки (для предопределенных объектов оболочки).

Например, если вы хотите зарегистрировать обработчик расширений контекстного меню для MyProgram.1, сначала создайте следующий подраздел:

HKEY_CLASSES_ROOT
   MyProgram.1
      ShellEx
         ContextMenuHandlers

Для следующих обработчиков создайте подраздел под ключом "Имя подраздела обработчика", имя которого является строковой версией CLSID расширения оболочки. В ключе имени подраздела обработчика можно зарегистрировать несколько расширений, создав несколько подразделов.

Обработчик Интерфейс Имя подраздела обработчика
Обработчик контекстного меню IContextMenu ContextMenuHandlers
Обработчик перехватчика копирования ICopyHook CopyHookHandlers
Обработчик действия перетаскивания IContextMenu DragDropHandlers
Обработчик страницы свойств IShellPropSheetExt PropertySheetHandlers
Обработчик поставщика столбцов (не рекомендуется в Windows Vista) IColumnProvider ColumnHandlers

 

Для следующих обработчиков значением по умолчанию ключа "Имя подраздела обработчика" является строковая версия 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-0000000000046}
Ссылка на оболочку (ANSI) IShellLinkA {000214EE-0000-0000-C000-00000000000046}
Ссылка на оболочку (ЮНИКОД) IShellLinkW {000214F9-0000-0000-C000-0000000000046}
Структурированное хранилище IStorage {00000000B-0000-0000-C000-0000000000046}
Метаданные IPropertyStore PropertyHandler
Метаданные IPropertySetStorage (не рекомендуется в Windows Vista) PropertyHandler
Закрепление в меню "Пуск" IStartMenuPinnedList {a2a9545d-a0c2-42b4-9708-a0b2badd77c8}
Закрепление на панели задач {90AA3A4E-1CBA-4233-B8BB-535773D48449}

 

Подразделы, указанные для добавления закрепить в меню "Пуск " и "Закрепить на панели задач" в контекстном меню элемента, необходимы только для типов файлов, включающих запись IsShortCut .

Поддержка обработчиков поставщиков столбцов была удалена в Windows Vista. Кроме того, начиная с Windows Vista, IPropertySetStorage является устаревшим в пользу IPropertyStore.

Хотя IExtractImage по-прежнему поддерживается, IThumbnailProvider является предпочтительным для Windows Vista и более поздних версий.

Предопределенные объекты оболочки

Оболочка определяет дополнительные объекты в HKEY_CLASSES_ROOT которые можно расширить так же, как типы файлов. Например, чтобы добавить обработчик страниц свойств для всех файлов, можно зарегистрировать с помощью ключа PropertySheetHandlers .

HKEY_CLASSES_ROOT
   *
      shellex
         PropertySheetHandlers

В следующей таблице приведены различные подразделы HKEY_CLASSES_ROOT , в которых можно зарегистрировать обработчики расширений. Обратите внимание, что многие обработчики расширений не могут быть зарегистрированы во всех перечисленных подразделах. Дополнительные сведения см. в документации по конкретному обработчику.

Подраздел Описание Возможные обработчики Версия
* Все файлы Контекстное меню, страница свойств, глаголы (см. ниже) Все
AllFileSystemObjects Все файлы и папки файлов Контекстное меню, страница свойств, глаголы 4,71
Папка Все папки Контекстное меню, страница свойств, глаголы Все
Каталог Папки файлов Контекстное меню, страница свойств, глаголы Все
Каталог\Фон Фон папки файлов Только контекстное меню 4,71
Диске Все диски в MyComputer, например "C:\" Контекстное меню, страница свойств, глаголы Все
Network Вся сеть (в разделе Мои сетевые расположения) Контекстное меню, страница свойств, глаголы Все
Network\Type\ # Все объекты типа # (см. ниже) Контекстное меню, страница свойств, глаголы 4,71
NetShare Все сетевые ресурсы Контекстное меню, страница свойств, глаголы 4,71
NetServer Все сетевые серверы Контекстное меню, страница свойств, глаголы 4,71
network_provider_name Все объекты, предоставляемые поставщиком сети "network_provider_name" Контекстное меню, страница свойств, глаголы Все
принтеры; Все принтеры Контекстное меню, страница свойств Все
AudioCD Аудио компакт-диск в 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 Windows", а соответствующий network_provider_name— Microsoft_Windows_Network.

Пример регистрации обработчика расширений

Чтобы включить определенный обработчик, создайте подраздел под ключом типа обработчика расширений с именем обработчика. В оболочке не используется имя обработчика, но оно должно отличаться от всех других имен в подразделе этого типа. Задайте значение по умолчанию подраздела name в строковой форме 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