Упрощенное обновление приложений в .NET - PullRequest
0 голосов
/ 08 декабря 2011

Автоматическое обновление настольного приложения кажется сложной проблемой в .NET.Существует целый ряд решений, от clickonce от Microsoft, до различных платных и открытых решений.Шаблон во всех этих случаях:

1 проверка удаленного сервера на наличие версии для запуска
2 загрузка новой версии
3 распаковка во временную папку
4 запуск процесса подстановки для заменыстарые файлы с новыми после того, как приложение закрывается
5 убивает работающее приложение, чтобы процесс shim мог начать работать
6 перезапускает главное приложение

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

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

, например:

Thread helper;
int currentVersion=0;

static void Main()
{
  //dumb loop, functions as a loader
  while(true)
  {
      var remoteVersion = GetRemoteVersion();
      if(remoteVersion > currentVersion)
      {
         if(helper != null)
         {
            //kill thread gracefully :)
         }

         currentVersion = remoteVersion;
         byte[] bytes = GetRemoteDllAsByteArray();
         var asm = Assembly.Load(bytes);
         var t = asm.GetType("a known type with a static method called Start()");
         var mi = t.GetMethod("Start");

         //run this on a helper thread outside the main loop:
         // the start method is the entry point to your application
         helper= new Thread(() => mi.Invoke(null,null));
         helper.SetApartmentState(ApartmentState.STA); //for winforms/wpf
         helper.Start();
      }


      Thread.Sleep(1 day);//only check for new versions once a day
  }   
}

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

1 Ответ

1 голос
/ 08 декабря 2011

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

Примечание

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

Зависимости

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

Для этого вы можете использовать простой подход (Pack / Unpack):

  • Запись / чтение(на стороне клиента) имя сборки
  • Запись / чтение байтового размера двоичного файла как Int32
  • запись байтов сборки в файл / чтение байтовсборка и запись на диск или в пользовательскую файловую систему
  • Продолжайте до тех пор, пока каждый файл не будет упакован / распакован

При разрешении зависимостей вы можете использовать что-то похожее на этот пример: Сборка, загружаемая с помощью Assembly.LoadFrom () на удаленном компьютере, вызывает исключение SecurityException

Обновления

Эту систему также можно использовать для создания пакетов обновлений для каждого обновления версии (например, 1.0 -> 1.5или 1.3 -> 1.5).Это позволяет избежать большого количества трафика, если вы сначала проверите устаревшие файлы и создадите пакет для каждого обновления версии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...