Тихое обновление с ClickOnce

Сложность 200

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

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

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

Подготовка

Перед тем как рассказать о «тихом» обновлении, следует дать вводную, на основе чего будет осуществляться доработка.

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

Про настройку публикации речь не пойдет, это стоит поискать самостоятельно.

Для пущей радости пусть еще приложение не будет подписано, хотя работающий сертификат не сильно изменит общий алгоритм.

Обычный процесс

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

  1. Проверка новой версии
  2. Вопрос о загрузке новой версии
  3. Закачка
  4. Вопрос от UAC о повышении прав
  5. Установка
  6. Запуск

По сути первые 5 пунктов для пользователя являются обременительными действиями, которые только раздражают. Автоматическое обновление, насколько я вижу, упрощает жизнь пользователю, если приложение запущено, то почти все можно сделать в фоновом режиме.

Внедрение

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

Сначала рассмотрим необходимые модификации в коде приложения. Их будет совсем немного:

  • Установить периодичность обновления
  • Подписаться на события о процессе обновления. Опционально. Будет отображаться ход закачки данных.  ProgressChanged.
  • Подписаться на событие об окончании обновления. Возникает раньше, чем заканчивается закачка данных приложения и манифеста. Completed.

Периодичность проверки обновлений можно задать в конструкторе в виде количества миллисекунд, что не очень удобно, либо в виде структуры TimeSpan, что конечно гораздо удобнее.

При подписке на события о процессе обновления, вам доступна информация из самописного события UpdateProgressChangedEventArgs, в котором определено свойство StatusString. В это свойство записывается информация о ходе обновления.

При окончании обновления требуется перезагрузить приложение специальным образом с помощью метода Restart(). Это делается при наступлении второго события (Completed).

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

Эту строку получить совсем не сложно, для этого есть два пути:

  1. Если во время установки приложения был создан ярлык, то его можно открыть в notepad++ и просто скопировать содержимое. Самый легкий способ.
  2. Необходимо точно прописать адрес до папку установки, до файла с расширением .application. Далее надо открыть этот файл и найти значение PublicKeyToken после чего скопировать его в целевую строку в приложении. В том же файле стоит уточнить архитектуру процессора и культуру.

Приложение со статусной строкой в тестовом варианте выглядело так:

01

 

Механика

Как я уже упомянул ранее, все основано на классе ApplicationDeployment, инициируя вызовы его методов мы можем получить всю необходимую информацию.

Основными событиями для подписки являются:

  • CheckForUpdateCompleted
  • UpdateCompleted
  • UpdateProgressChanged

В пояснениях события не нуждаются я думаю, они и так себя хорошо описывают.

По таймеру запускается проверка обновлений с помощью метода CheckForUpdateAsync() класса ApplicationDeployment. После того как проверка прошла, дергается событие CheckForUpdateCompleted, а по этому событию мы уже пытаемся загрузить обновления с помощью метода UpdateAsync(). После того как асинхронное обновление завершено требуется только сообщить об этом пользователю и подготовить код для перезапуска приложения.

Для перезапуска приложения распространяемого с помощью ClickOnce, потребуется специальный файл с расширением .appref-ms, который мы и создадим, заполнив файл строкой которую я упоминал в разделе внедрения кода. Далее требуется его запустить стандартными методами как процесс.

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

 

Не вижу смысла в данном случае детально расписывать все, так как лучше посмотреть на код и на описание класса в MSDN, все реально держится и крутится вокруг одного класса.

Развитие

Конечно есть жуткое желание оформить это как NuGet пакет, однако надо побольше подумать, как именно будет использоваться пакет. Наиболее утилитарным мне видится ограничение класса SilentUpdater до единственного события OnUpdateCompleted и метода Restart(). Я не вижу большой пользы в том, чтобы пользователь видел сколько данных уже загрузилось, да какого они типа. Все это лишнее. Пользователю стоит только сказать о том, что есть новая версия и она готова к установке. Больше ничего волновать не должно.

Да, наверно так и стоит сделать в самом ближайшем будущем.

Так же стоит упомянуть, что на мысли о статье меня навела заметка в CodeProject.

 

Исходный код

 

 

Hard’n’Heavy!

 

 

Оставить комментарий