Главная > Популярный софт > Создание приложения с полной поддержкой плагинов

Создание приложения с полной поддержкой плагинов

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

Затраты: даром!

С эпизода существа моей 1 версии прибавления Utility Runner прошло теснее немного месяцев. Utility Runner разрешает исполнять системные утилиты с минимальными издержками: взамен кучи указателей на панели задач, огромных EXE-файлов (и стимулированных ними неудобств, связанных с памятью и временем пуска) данное прибавление правит большим количеством утилит из 1-го места.

Чтобы открыть данное решение, вам потребуется, по крайней мере, Visual Studio 2008 Express Edition (Visual C# или же Visual Basic). Если у вас пока нет данной среды исследования, вам стоит позаботиться о ее получении!

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

Большая неувязка мне содержалась в том, чтоб воплотить диспетчер для помощи тысячи надстроек-утилит — как в Firefox. MEF разрешает с легкостью помечать, какие классы считаются надстройками и как они обязаны быть соединены с вашим кодом в общем, хотя мне хотелось наибольшего. Поразмыслив, я посчитал, что мои цели таковы:

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

Загрузка надстроек как правило обрабатывается лично инфраструктурой MEF, и все же, некоторая ручная работа все таки будет нужно. Я принял решение, что заместо ревизии папки на присутствие подходящих DLL, как в 1 версии, лучше применять обычный формат упаковки и помещать надстройку и связанные с ней файлы в 1 контейнер.

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

Перед загрузкой DLL с надстройками класс AddinManager сканирует папку надстроек на присутствие файлов с расширениями .util и распаковывает их в одноименные папки. Каждая из таковых папок прибавляется в перечень папок, которые просматриваются MEF. После данного начальный файл удаляется.

В прибавлении, поддерживающем надстройки, необходим некий метод, при помощи которого юзеры имели возможность бы прибавлять свежие надстройки. Самый несложный метод — перетаскивание новейших файлов .util в папку Addins, хотя действительно он не очень понятен на интуитивном уровне. Мне хотелось, чтоб юзер имел возможность установить надстройку одним щелчком клавиши.

Если юзер щелкает клавишу Add New Addin From File , он практически раскрывает диалоговое окошко для поиска файла. Выбранный файл копируется в папку Addins, и прибавление уведомляет юзера про то, что свежая надстройка станет загружена при последующем запуске прибавления. Было бы замечательно загружать надстройку безотлагательно, и MEF поддерживает данное, хотя из-за простоты я принял решение не использовать динамическое управление надстройками.

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

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

Для отключения надстройки довольно переименовать папку надстройки. Однако данное нельзя во время исполнения, потому что все загруженные DLL блокируются в файловой системе. В качестве кандидатуры я сделал файл (никакой длины) с таким же фамилией и добавил к нему расширение .disable. Проверка продемонстрировала, что данный вариант абсолютно трудоспособен.

Включение и удаление надстроек обрабатываются так же, при всем этом применяются файлы никакой длины с расширениями .enable и .delete в соответствии с этим.

Чтобы сделать надстройку, вам необходимо, в первую очередь, воплотить интерфейс IWpfService , а так же, прибавить атрибут WpfServiceMetadata под названием вашей надстройки. После данного не позабудьте воплотить все способы интерфейса. Метод Start вызывается при инициализации (постарайтесь не проводить большое количество времени в конструкторе), а Stop — в конце, при очистке. Обновляя Status , непременно генерите событие StatusChanged .

[WpfServiceMetadata( "SampleAddin" )] public class SampleAddinImpl : IWpfService { }

Наконец, вам пригодится скопировать DLL собственной надстройки в папку под названием данной надстройки и расширением .util. (Да, как раз так: расширение присваивается фамилии папки.) Я делаю данное в Visual Studio при помощи действия, генеримого в последствии производства плана. В режиме отладки прибавление выискивает папку Addins в текущем каталоге. При обычном запуске (к примеру, опосля установки) просматривается локальный профиль юзера.

Когда вы готовьтесь к распространению надстройки, заархивируйте DLL и всевозможные сопутствующие файлы в ZIP-файл, а после этого переименуйте расширение .zip в .util. Этот файл возможно загружать со странички Addins в параметрах прибавления либо вручную перемещать его в папку MefUtilRuner \ Addins , творимую в папке вашего локального профиля ( c :\ users \{ USERNAME }\ AppData ):

Информационные окошки, подсказки повторяющий вид реплик, строчки состояния — это все хорошие методы показывать известия юзеру, хотя они дозволяют демонстрировать только 1 строчку одновременно. Если юзер не успеет прочитать 1-ое известие, вывод 2 известия даст почву тому, что 1-ое из их просто пропадет. Существуют удовлетворительные диспетчеры известий, делающие легче управление большим количеством извещений, хотя я принял решение остановиться на интегрированном провайдере подсказок повторяющий вид реплик и осуществлять контроль частоту отправки конфигураций. В целом данное провайдер буферизуемых подсказок, который не более чем указывает известия любые x секунд самостоятельно от того, какое количество известий передает прибавление. Для его применения добавьте составляющие в набор. Всякий разов, как скоро делается легкодоступным некоторой составляющую, генерируется событие. Если срок существования составляющей превзойдет пороговое значение, юзеры комплекта ни разу не заметят его.

// Повторяем, пока же есть составляющие (вероятна готовность // незамедлительно нескольких частей) while (item != null ) { // Если данное ветхий составляющая, событие не генерируется. // Это вполне вероятно, когда // процесс входит в цикл и копирует много // деталей за слишком краткий // зазор времени. if (DateTime.Now.Subtract(item.TimeStamp).TotalMilliseconds < _maxTTL) { RaiseEvent(item.Item); Thread.Sleep(_interval); } item = default (ItemWrapper); lock (_lock) { if ( _items.Count > 0 ) item = _items.Dequeue(); } }

Основное окошко восоздает экземпляр класса TimedQueue. Всякий разов, как скоро надстройке необходимо вывести известие, оно прибавляется в набор. Когда действует событие ItemAvailableEvent , оно следует UI-потоку для отображения известия. Диспетчеризация предотвращает трудности прямой передачи известий меж фоновым потоком TimedQueue и UI-потоком.

void statuses_ItemAvailableEvent( object sender, ItemAvailableEventArgs e) { Dispatcher.BeginInvoke((ThreadStart) delegate () { StatusUpdatedHandler(e.Item); } , DispatcherPriority.Background); }

Хотя данный экземпляр применяется для известий состояния, у вас есть возможность использовать TimedQueue и для иных целей, как скоро есть потребность в удалении обветшавших известий. Один из образцов — «регулирование» пользовательского ввода в игровой програмке, где навряд ли необходимо позволять многократный пламя из орудия или же чрезмерно нередкие прыжки.

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

Кроме того, для развертывания утилит бы была может быть полезна разработка ClickOnce. Она комфортна и понятна юзеру, и у нее есть своя стоимость: ClickOnce в значительной степени ограничивает то, как прибавления имеют все шансы взаимодействовать с системой. Приложения практически постоянно инсталлируются персонально для точного юзера и вмещаются в «тайные» папки. Разработчики не имеют возможности считывать либо записывать на твердый диск — лишь в защищенное хранилище (подобно iPhone, полагаю). Не не сомневается на предмет иных ограничений, да и такое может сделать проблемы.

Также бы было примечательно в силе прибавлять надстройки во время исполнения. Это сравнимо несложная функция, и у меня пока же не дошли руки до нее. При данном можнож бы было ждать и реализации подключения/отключения/удаления во время исполнения. Увы, подлинное отключение и удаление по-настоящему невероятны. Конечно, я имел возможность бы вызывать Stop для точной утилиты и устранять ее из UI (и при последующем запуске не вызвать Start ей), хотя на практике данная утилита как и прежде выполнялась бы до перезапуска прибавления. Принудительно удалить ее невозможно, раз не применять отдельные домены прибавления, а копаться с ими мне совершенно не охото.

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

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

Arian Kulp — разраб ПО, живет в Западном Орегоне. Создает образцы, демо-ролики, лабораторные занятия и сообщает заметки, выступает на всевозможных событиях, приуроченных к вопросцам программирования, и еще с превеликим удовольствием проводит свободное время со собственной семьей.

This post originated from and is provided by the MSDN Blogs RSS feed. The original post of the article can be found here .

This entry was posted on Saturday, January 30th, 2010 at 5:10 amand is filed under MSDN Blogs . You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

Популярный софт

  1. Комментариев пока нет.
  1. Трекбеков пока нет.