Как написать расширение оболочки на C ++? - PullRequest
17 голосов
/ 11 января 2012

Это казалось обычным вопросом, но после некоторых поисков я не смог найти ответы на свои вопросы. Вот статья на эту тему:

http://www.codeproject.com/KB/shell/shellextguide1.aspx

Но это для очень старой версии Visual Studio. Я использую VS 2008, поэтому инструкции и интерфейсы не соответствуют тому, что я вижу.

Я хочу создать простое расширение оболочки, используя C ++, которое создает контекстное меню для файлов с расширением .GZ. Если щелкнуть правой кнопкой мыши эти файлы, я смогу щелкнуть по своему пункту контекстного меню и получить обратный вызов в коде, чтобы выполнить какую-то операцию с этим файлом.

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

Из того, что я видел, ATL используется для этого, но я никогда не использовал ATL, поэтому все типы объектов и интерфейсы меня очень смущают. Это было бы не так плохо, если бы у меня был подходящий учебник или документация для чтения.

Кто-нибудь может мне помочь? Есть ли какое-нибудь учебное пособие, которому нет 10 лет?

1 Ответ

24 голосов
/ 12 января 2012

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

  • С расширением оболочки вы можете динамически создавать пункт контекстного меню (или подменю), который более соответствуетвыбранный файл (ы).Например, если вы пишете расширение оболочки для zip-файлов, можно создать подменю в контекстном меню, которое отображает все содержимое zip-файла.
  • Вы можете обрабатывать несколько файлов одновременно, что может бытьболее выгодно не только для повышения производительности, но и для того, чтобы вы могли решить, что делать, основываясь на выделении в целом, а не только для каждого файла.

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

  • Значительно увеличена сложность.Будьте готовы потратить много усилий, чтобы это заработало.Возьмите домашний эспрессо-аппарат рядом с вашим компьютером и / или наймите кого-нибудь, чтобы приготовить вам кофе.

  • Значительно увеличена сложность в отладке.То же самое и о кофе.

Трудно написать расширение оболочки, потому что его очень сложно отладить.

  • Расширения оболочки загружаютсяПроцесс explorer.exe, и без специальной настройки Explorer вам необходимо принудительно завершить процесс explorer.exe, чтобы установить более новую версию расширения Shell.Есть способ заставить Проводник выгружать библиотеки DLL, которые он больше не использует, но вы должны делать это только на компьютере разработчика, а не на цели развертывания:

    1. В RegEdit просмотритек следующему ключу:

      HKEY_LOCAL_MACHINE \ SOFTWARE \ Microsoft \ Windows \ CurrentVersion \ Explorer

    2. Добавьте новый ключ DWORD с именем AlwaysUnloadDLL и установите его значение равным 1.

    3. Перезапустите проводник.

    Это работает большую часть времени, но все еще могут быть случаи, когда вам нужно закрыть Explorer, поскольку расширение оболочки не было выгружено.

  • Имейте в виду, что ваше расширение Shell может загружаться другими приложениями, например, если вы щелкнете правой кнопкой мыши файл с диалоговым окном «открыть файл» приложения, тогда ваше расширение Shell будетзагружается в это приложение, а не в Explorer.

  • Если расширение оболочки вызывает ошибку во время выполнения, довольно часто результатом будет просто то, что ваш пункт контекстного меню будетне отображается, очень редко вам сообщают, что не удалось загрузить расширение Shell или что оно вызвало ошибку времени выполнения.
  • Конфигурация может быть сложной, даже при установке данные реестра необходимо создавать в нескольких местах.и в зависимости от того, где вы хотите, чтобы ваше контекстное меню отображалось, места в реестре могут отличаться в разных версиях Windows.

Что вам нужно сделать:

  • Visual Studio предлагает несколько ярлыков для создания расширений оболочки, но в основном вам нужно создать COM DLL.Расширение оболочки для пунктов контекстного меню должно реализовывать как интерфейс IContextMenu, так и интерфейс IShellExtInit.
  • В IShellExtInit::Initialize() метод, вы можете получить выбранные файлы из параметра IDataObject.Из памяти данные представлены в формате «Drag-n-Drop», поэтому вам нужно получить дескриптор HDROP из IDataObject и запросить файлы оттуда (это из памяти, оно может фактически отличаться отЯ описал здесь, поэтому будьте осторожны).
  • Когда ваша DLL готова к «установке», вы должны скопировать ее куда-нибудь, а затем запустить regsvr32, чтобы убедиться, что она зарегистрирована.
  • Следуйте этому руководству , чтобы узнать, куда помещать ключи реестра.
  • Там может иметь проблемы с 64-битной Windows, если вы создаете 32-битную DLL, этоможет не загружаться в 64-разрядном обозревателе ... имейте это в виду, если у вас возникают проблемы с 64-разрядным Windows.
  • Ваша DLL на самом деле будет иметь два GUID, связанных с ним.Я не могу точно вспомнить, как это работает, но один GUID относится к самой DLL, а другой относится к фактическому расширению оболочки.Убедитесь, что вы используете GUID фактического Shell Extension при создании ключей в реестре, где требуется GUID.

Все учитывается… (tl; dr)

Взвесьте стоимость того, стоит ли расширение Shell.Если вы хотите создавать пункты меню динамически на основе выбранных файлов, тогда расширение Shell может быть единственным способом.Если вы хотите обрабатывать все файлы одновременно, вам, вероятно, понадобится также расширение оболочки.

Альтернативой методу контекстного меню может быть назначение цели drag-n-drop на рабочем столе пользователя иличто-то.Изучите другие способы, с помощью которых пользователь может отправить ваши файлы в ваше приложение, поскольку расширение оболочки часто требует гораздо больших усилий, чем оно того стоит.Я нашел это трудным путем, и я думаю, что все остальные тоже.

...