четверг, 19 июня 2008 г.

Shell Extension Handlers на .NET

Вчера разбирался с Shell Extension-ами нашего проекта. Мне предстояло сделать что-бы контекстное меню для определённой иконки на десктопе формировалось динамически. Решил погуглить на счет примера реализации системного интерфейса IContextMenu на .net и вот какую вешь обнаружил. Оказывается Майкрософт крайне не рекомендует реализовывать Shell Extension Handler-ы на .net, и особенно те которые могут загружаться в процессы (in-process shell extensions). Вот ссылка на на оригинальное сообщение Jesse Kaplan, (одного из CLR Program Manager), а ниже мой вольный перевод его слов:

К сожалению, единственный способ реализовать их – это неуправляемый С++ . Создание расширителей оболочки, которые загружаются в процесс (in-process shell extensions), это в действительности очень опасная вешь, поскольку таким образом вы можете внедрить управляемый код (и .NET Framework) в каждое приложение на машине, у которого есть стандартный Windows-диалог для открытия файлов.

Проблемы возникают из-за того что только одна версия .NET Framework может быть загружена в процесс (другие компоненты предназначенные для совместного использования как java и msxml имеют те же свойства и как следствие те же ограничения).

Если вы напишете ваш расширитель оболочки на .NET Framework 2.0 , а приложение написанное на .NET Framework 1.1 создаст стандартный диалог для открытия файлов ваш расширитель сгенерирует ошибку, так как не сможет работать на младшей версии. Все может стать еще даже хуже если ваш расширитель загрузится в процесс раньше другого приложения на .net. Наличие вашего расширителя может привести к тому что приложению придётся работать на версии рантайма, на которую оно не было рассчитано и оно упадёт. Из-за всех этих проблем мы настоятельно рекомендуем не использовать исполняющие среды и библиотеки, которые поддерживают загрузку только единственной версии в процесс (такие как .NET Framework, java, or msxml) для разработки расширителей оболочки.

Вот такие дела. Тем не менее, если все таки кому-то надо реализовывать расширители оболочки, то хороший пример находится совсем рядом: VS2003Dir\SDK\v1.1\Samples\Technologies\Interop\Applications\ShellCmd,

где VS2003Dir – это каталог, где установлена 2003 студия.

4 комментария:

BrigOS комментирует...

Проблемы возникают из-за того что только одна версия .NET Framework может быть загружена в процесс.
Да не правда это. Разные версии .net компонет грузятся в один процесс безо всякого палива. Вроде у Сергея Розовика в блоге как то проскакивал пост на эту тему.

Андрей Бороздин комментирует...

Привет! К сожалению, но ты ошибаешься. Вот цитата из книги Steven Pratschner, "Customizing the Microsoft® .NET Framework Common Language Runtime", Chapter 3. Controlling CLR Startup and Shutdown, раздел The CLR Startup Configuration Settings
,

only one version of the CLR can be loaded into a process, and once that version has been loaded, it cannot be unloaded and replaced with another version.

BrigOS комментирует...

Чуть нашел
http://stump-workshop.blogspot.com/2007/04/blog-post_13.html

Андрей Бороздин комментирует...

Я посмотрел пост, на который ссылается Сергей. Там о другом идет речь. Во первых меня очень смутил приведенный код. По нему видно, что сборка, скомпилированная под net.1.1 грузится в процесс, скомпилированный под net 2.0 и исполняется она на рантайме и библиотеках net 2.0 и не более. Это вполне нормальная ситуация и называется обратная совместимость. Приведенный код исполняется на рантайме net 2.0 (это подтверждается и утверждается самим примером) и на библиотеках net 2.0. Это легко проверить либо при помощи студийного окна Modules (Debug->Windows->Modules) либо написать небольшой код по выводу загруженных сборок.
Во фрагменте, что я привел и перевел, говорится, прежде всего, о загрузке рантайма (исполняющей среды) и основных библиотек (например, mscorlib).