Руководство по реализации расширений In-Process

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

Одной из конкретных заметок является среда CLR, также известная как управляемый код или платформа .NET Framework. Корпорация Майкрософт рекомендует не создавать управляемые внутрипроцессные расширения в Windows Обозреватель или Windows Internet Обозреватель и не считает их поддерживаемым сценарием.

В этом разделе рассматриваются факторы, которые следует учитывать при определении того, подходит ли какая-либо среда выполнения, кроме среды CLR, для использования внутрипроцессными расширениями. Примеры других сред выполнения включают Java, Visual Basic, JavaScript/ECMAScript, Delphi и библиотеку среды выполнения C/C++. В этом разделе также приводятся некоторые причины, по которым управляемый код не поддерживается во внутрипроцессных расширениях.

Конфликты версий

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

Рассмотрим внутрипроцессное расширение, написанное с использованием версии среды CLR, предшествующей версии 4.0. Каждое приложение на компьютере, использующее диалоговое окно "Открыть файл" , потенциально может иметь управляемый код диалогового окна и его сопутствующие зависимости CLR в процесс приложения. Приложение или расширение, которое сначала загружает версию среды CLR до 4.0 в процесс приложения, ограничивает, какие версии среды CLR могут быть использованы в дальнейшем этим процессом. Если управляемое приложение с диалоговым окном "Открыть " создано на основе конфликтующей версии среды CLR, расширение может работать неправильно и вызвать сбои в приложении. И наоборот, если расширение первым загружается в процессе, а конфликтующая версия управляемого кода пытается запустить после этого (возможно, управляемое приложение или запущенное приложение загружает среду CLR по запросу), операция завершается сбоем. Для пользователя кажется, что некоторые функции приложения случайным образом перестают работать или приложение таинственным образом аварийно завершает работу.

Обратите внимание, что версии среды CLR, равные или более поздней версии 4.0, как правило, не подвержены проблеме управления версиями, так как они предназначены для сосуществования друг с другом и с большинством версий среды CLR до 4.0 (за исключением версии 1.0, которая не может сосуществовать с другими версиями). Однако могут возникнуть проблемы, отличные от конфликтов версий, как описано в оставшейся части этой статьи.

Проблемы с производительностью

Проблемы с производительностью могут возникнуть при загрузке в процесс сред выполнения, что значительно влияет на производительность. Снижение производительности может быть в виде использования памяти, использования ЦП, затраченного времени или даже адресного пространства. Среда CLR, JavaScript/ECMAScript и Java являются средами выполнения с высокой степенью влияния. Так как внутрипроцессные расширения могут загружаться во многие процессы и часто делаются это в моменты, зависящие от производительности (например, при подготовке меню для отображения пользователя), среда выполнения с высоким уровнем влияния может негативно сказаться на общей скорости реагирования.

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

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

Проблемы, связанные с платформа .NET Framework

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

Повторная запись

Если среда CLR блокирует поток с одним потоком (STA), например из-за инструкции Monitor.Enter, WaitHandle.WaitOne или утверждения блокировки , среда CLR в своей стандартной конфигурации переходит во время ожидания вложенного цикла сообщений. Многие методы расширения запрещены для обработки сообщений, и такая непредсказуемая и непредвиденная повторный вход может привести к аномальному поведению, которое трудно воспроизвести и диагностировать.

Многопоточные квартиры

Среда CLR создает вызываемые оболочки среды выполнения для объектов COM. Эти же вызываемые оболочки среды выполнения уничтожаются позже методом завершения среды CLR, который является частью многопоточного объекта (MTA). Для перемещения прокси-сервера из STA в MTA требуется маршалирование, но не все интерфейсы, используемые расширениями, можно маршалировать.

Время существования недетерминированных объектов

Среда CLR имеет более слабые гарантии времени существования объекта, чем машинный код. Многие расширения имеют требования к количеству ссылок для объектов и интерфейсов, и модель сборки мусора, применяемая средой CLR, не может выполнить эти требования.

  • Если объект CLR получает ссылку на COM-объект, ссылка на COM-объект, удерживаемая вызываемой оболочкой среды выполнения, не освобождается до тех пор, пока вызываемая оболочка среды выполнения не будет собрана мусором. Недетерминированное поведение выпуска может конфликтовать с некоторыми контрактами интерфейса. Например, метод IPersistPropertyBag::Load требует, чтобы объект не сохранял ссылку на контейнер свойств при возврате метода Load .
  • Если ссылка на объект CLR возвращается в машинный код, вызываемая оболочка среды выполнения откажает свою ссылку на объект CLR при последнем вызове оболочки среды выполнения в Release , но базовый объект CLR не будет завершен до тех пор, пока не будет собран мусор. Недетерминированное завершение может конфликтовать с некоторыми контрактами интерфейса. Например, обработчики эскизов должны освобождать все ресурсы немедленно, когда их количество ссылок падает до нуля.

Допустимое использование управляемого кода и других сред выполнения

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

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

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

  • IExecuteCommand связан с записью DelegateExecute, зарегистрированной в подразделекомандыкоманд оболочки\\.
  • IDropTarget, связанный с ИДЕНТИФИКАТОРом CLSID, зарегистрированным в подразделе команды оболочки\\DropTarget.
  • IExplorerCommandState связан с записью CommandStateHandler, зарегистрированной в подразделе команд оболочки\.