Visual Basic, .NET, ASP, VBScript
 

   
   
     

Форум - Общий форум

Страница: 1 |

 

  Вопрос: Самообновление программы Добавлено: 29.04.03 17:06  

Автор вопроса:  brown

Помогите плиз! Хочется делать всё по-взрослому :)
Подскажите пожалуйста как это можно сделать, чтобы прога заменила сама себя при запуске, когда выяснит, что версия устарела.
Особенно меня интересует, как можно выкачать новый экзешник проги или разных компонентов приложения (ocx-ы всякие, dll-ки), из базы MS SQL2000; зарегистрить их и запустить уже обновлённый экзешник.
И ещё вопрос можно ли это сделать всё в той проге, которую юзерь запустил, не зная, что она устарела, а не писать дополнительно прогу обновления, которая запускается из шела и всё это делает

Если есть примеры кодов буду очень признатаелен. Или подскажите где есть в инете.

Ответить

  Ответы Всего ответов: 15  

Номер ответа: 1
Автор ответа:
 DAN



ICQ: 234826 

Вопросов: 10
Ответов: 124
 Web-сайт: visualbasic.boom.ru
 Профиль | | #1
Добавлено: 30.04.03 05:48

Пусть прога записывает свою версию в ini файл или в реестр. При запуске прочитает и заменит себя!

Ответить

Номер ответа: 2
Автор ответа:
 brown



Вопросов: 11
Ответов: 12
 Профиль | | #2 Добавлено: 30.04.03 08:25

Куда записать верию проги я придумаю. :)

Как заменить запущенный экзешник и перезапустить его?
Если есть пример кода, плиз!

Ответить

Номер ответа: 3
Автор ответа:
 Павел



Администратор

ICQ: 326066673 

Вопросов: 368
Ответов: 5968
 Web-сайт: www.vbnet.ru
 Профиль | | #3
Добавлено: 30.04.03 10:11

Создавай bat'ник, который в цикле будет пытаться заменить твою прогу обновлённой весрией, пока не получится, после этого пускает новую версию проги.

Это если я правильно понял суть вопроса.

Ответить

Номер ответа: 4
Автор ответа:
 Mozgoed



Вопросов: 0
Ответов: 1
 Профиль | | #4 Добавлено: 12.03.10 00:31
Итак! Подробнейшее описание программы самообновления для .Net Framework 2.0 (Dot Net 2.0)
Язык - C# (C Sharp)
Так как я давно мучился такой проблемой, то пришлось перепробовать многое)) В первую очередь никому не хочется довешивать свои программы сторонними dll'ками. Хочется или встроенного решения от родной библиотеки или исходники проги, чтобы нагло вставить их к себе и жить счастливо.
Встроенное решение для .Net 2.0 - ClickOnce меня не впечатлило. Самая плохая идея у них в том, что необходимо устанавливать приложение в систему =( . Вместо того чтобы просто заменять нужные файлы у вас в папке - она полностью переселяет вашу прогу на сайт. И даёт вам лишь жалкий файлик с расширением ".application" через который вы обречены каждый раз выкачивать свою программу. Конечно тут есть и плюсы: у пользователя всегда самая последняя прога. Все dll'ки не выкачиваются, а подгружаются по мере надобности.
Но у большинства людей проги выполнены в моно варианте. Один exe'шник и всё!
Вариант с bat'ником тоже не вдохновляет. И выглядит слишком устарело и кустарно. Перед пользователем обязательно промелькнёт окно консоли и ваша прога станет ему напоминать либо вирь, либо кряк)) что практически одно и то же)))
Я решил самообновлялку написать полностью своими руками и используя только язык C#.
Поэтому вот мой вариант самообновлялки:
Самообновление состоит из 2х файлов. Первый файл - это собственно ваша основная программа. Будем считать что это Windows Application. Код для самообновления я вставил прямо в класс Program, перед кодом который отвечает за запуск формы. Ведь незачем грузить форму, если окажется, что прога устарела. Пожалейте свой компьютер)))

Для понимания того, что написано ниже нужно залить на ваш сайт txt файл следующего содержания (у нас это вымышленный http://mysite.ru/myprogram/update.txt):

1.0.0.1
http://mysite.ru/myprogram/updater.exe.gz
http://mysite.ru/myprogram/myprogram.exe.gz

Первая строчка - номер самой свежей версии
Вторая строчка - ссылка на программу самообновления
Третья строчка и все последующие - это файлы для обновления.
  1.  
  2. using System;
  3. using System.Net;
  4. using System.Windows.Forms;
  5. using System.IO;
  6. using System.Reflection;
  7. using System.Diagnostics;
  8. namespace SelfUpdate
  9. {
  10. static class Program
  11.     {
  12.         [STAThread]
  13.         static void Main(string[] args)
  14.         {
  15.             if (File.Exists("updater.exe")) //Проверяем на остатки от процесса обновления
  16.             {
  17.                 System.Threading.Thread.Sleep(2000); //Спим 2 секунды, пока обновлялка закроется
  18.                 File.Delete("updater.exe"); //Удаляем обновлялку
  19.             }
  20.             WebClient wc = new WebClient(); //Через ВебКлиент мы скачиваем файлы
  21.             const string updatestring = "http://mysite.ru/myprogram/update.txt"; //Это фиксированная ссылка на сайт, где лежит txt-файл с данными для обновления
  22.             const string updatername = "updater.exe"; //Тоже фиксированное имя обновлялки
  23.             Stream stream = null;
  24.             try{stream = wc.OpenRead(updatestring);} //Пытаемся скачать txt'шник. Он считывается не в файл, а обрабатывается прямо в памяти.
  25.             catch{ goto normalstart; } //Если не удалось типа инет лагает, то просто грузим текущую версию проги
  26.             StreamReader read = new StreamReader(stream); //Читалка текста в потоках
  27.             string newversion = read.ReadLine(); //Читаем первую строчку
  28.             string updater = read.ReadLine(); //Читаем вторую строчку
  29.             string[] separator = { "\r\n" }; //Enter - на самом деле выглядит так =)
  30.             string[] fileblowfiles = read.ReadToEnd().Split(separator, StringSplitOptions.RemoveEmptyEntries); //Получаем все остальные строчки разделенные Enter'ами
  31.             read.Close(); //Закрываем потоки
  32.             string version = Assembly.GetExecutingAssembly().GetName().Version.ToString(); //Этот метод получает версию текущей сборки. Т.е. версию вашей программы (Допустим она 1.0.0.0)
  33.             if (newversion != version) // Если версии не совпадают - значит прога устарела. Обновляем!
  34.             {
  35.                 string file = updatername;
  36.                 stream = wc.OpenRead(updater); //Скачиваем и распаковываем ссылку на updater.exe
  37.                 unzip.UnZip(stream, file); stream.Close();
  38.                 foreach (string fileblowfile in fileblowfiles) //Далее просто выкачиваем все остальные файлы. Думаю необходимости проверки их доступности нет. Ведь мы уже проверили update.txt на доступность через интернет. Но можно проделать то же самое и с каждый файлом при необходимости.
  39.                 {
  40.                     file = fileblowfile.Substring(fileblowfile.LastIndexOf('/') + 1); // превращает "http://mysite.ru/myprogram/myprogram.exe.gz" в "myprogram.exe.gz"
  41.                     wc.DownloadFile(fileblowfile, file); //скачивает файл
  42.                 }
  43.                 wc.Dispose(); //убиваем качалку
  44.                 Process.Start(updatername); //запускаем только что распакованный updater.exe
  45.                 return; //Немедленно выходим из нашей программы
  46.             }
  47.             normalstart: //Метка на которую переходим, если инет не работает или упал наш сайт.
  48.             Application.EnableVisualStyles();
  49.             Application.SetCompatibleTextRenderingDefault(false);
  50.             Application.Run(new SimpleForm());
  51.         }
  52.     }
  53. }


Далее необходимо пояснить, что все файлы на сайте, кроме update.txt запакованы GZip'ом. Им можно сжать, программой 7zip или WinRar. Я просто поставил там все настройки на максимум и всё работает. Дело в том, что Dot Net 2.0 умеет работать с GZip архивами. Так почему бы не съэкономить на трафике. И лишний раз не раздражать пользователя долгой закачкой файлов самообновления.
Вот метод UnZip, который распаковывает данные из потока в файл Я запихнул его в отдельный файл-класс. Комменторовать влом, поэтому просто немного msdn почитайте и про потоки файловые немного. И у вас всё получится =) . Вот он:
  1.  
  2. using System;
  3. using System.IO;
  4. using System.IO.Compression;
  5. namespace SelfUpdate
  6. {
  7.     class unzip
  8.     {
  9.         internal static void CopyStream(Stream from, Stream to)
  10.         {
  11.             byte[] buffer = new byte[1024];
  12.             short count = -1;
  13.             while (count != 0)
  14.             {
  15.                 count = (short)from.Read(buffer, 0, buffer.Length);
  16.                 to.Write(buffer, 0, count);
  17.             }
  18.         }
  19.         internal static void UnZip(Stream inputStream, string outputFile)
  20.         {
  21.             using (FileStream write = File.Create(outputFile))
  22.             using (GZipStream unzip = new GZipStream(inputStream, CompressionMode.Decompress))
  23.             {
  24.                 CopyStream(unzip, write);
  25.             }
  26.         }
  27.     }
  28. }


Теперь когда наша прога успешно выкачала все нужные компоненты и распаковала updater.exe, то самое время разобраться что же будет выполняться, когда он запустится.
updater.exe выполнен в виде Windows Application, удалены все строчки отвечающие за загрузку формы. И сама форма из проекта тоже удалена. Короче у вас должен остаться только один Program.cs и unzip.cs, в котором всё тот же метод для распаковки архивов.
К слову стандартные Dot Net 2.0 проги сжимаются GZip'ом чуть ли не 5-7 раз.
  1.  
  2. using System;
  3. using System.Net;
  4. using System.IO;
  5. using System.Diagnostics;
  6. namespace SelfUpdate
  7. {
  8.     static class Program
  9.     {
  10.         [STAThread]
  11.         static void Main(string[] args)
  12.         {
  13.             if (!File.Exists("myprogram.exe")) return; //Если рядом нет нашей основной проги, то возможно кто-то просто случайно её запустил))) выходим =)
  14.             for (int i = 0; i < 5; i++) //5 раз пытаемся удалить основной файл
  15.             {
  16.                 System.Threading.Thread.Sleep(2000); //Спим 2 секунды.
  17.                 try
  18.                 { File.Delete("FileBlow.exe"); break; } //Попытка удалить файл.
  19.                 catch
  20.                 { ; }
  21.             }
  22.             string[] files = Directory.GetFiles(Environment.CurrentDirectory, "*.gz", SearchOption.TopDirectoryOnly); //Получаем все файлы в текущей папке с расширением ".gz"
  23.             foreach (string file in files) //Для каждого такого файла делаем...
  24.             {
  25.                 Stream stream = File.OpenRead(file); //Открываем файл для чтения
  26.                 unzip.UnZip(stream, Path.ChangeExtension(file, null)); //Распаковываем в файл с таким же именем, только убираем расширение ".gz"
  27.                 stream.Close(); File.Delete(file); //Закрываем поток и удаляем уже ненужный архив.
  28.             } //После того как все архивы распаковали. В том числе и основной файл, то...
  29.             Process.Start("myprogram.exe"); //Запускаем уже новую версию нашей основной программы.
  30.         }
  31.     }
  32. }


Вот и всё!
Если вдуматься, то ничего сложного)))
Плюсы данной технологии самообновления:
- Файлы передаются в сжатом виде. Экономится время обновления и трафик пользователя
- Просто проверка версии занимаем в реале около 2-4 секунд. А трафик как вы уже поняли составляет размер того самого txt-файла, а значит это около 1 КБ (плюс-минус расходы на соединение и ошибки на линии =) )
- Обновление идёт в скрытом режиме. Пользователь ничего не замечает и просто ждёт.
- Обновлять можно целые списки файлов. А если немного дописать updater.exe, то можно даже структуру каталогов сохранять при распаковке.
Минусы:
- Всё таки тратится время на обновление. И у пользователя совсем не спрашивает разрешения))) Скорее всего фаерволы и касперские всякие заверещат о сетевой угрозе))) но это не так страшно.
- Нужно надыбать где-то GZip архиватор для подготовки файлов (7zip, WinRar)
- И самый огромный минус по сравнению с ClickOnce - нужно вручную готовить каждый новый релиз обновления. Заливать update.txt на сайт... Проверять работу всего этого...
Если вы не боитесь всего этого, то этот метод самообновления для ВАС! Удачи и до новых встреч!
Written by Mozgoed for .Net 2.0

Ответить

Номер ответа: 5
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #5 Добавлено: 13.03.10 02:37
Mozgoed пишет:
Встроенное решение для .Net 2.0 - ClickOnce меня не впечатлило. Самая плохая идея у них в том, что необходимо устанавливать приложение в систему =( . Вместо того чтобы просто заменять нужные файлы у вас в папке - она полностью переселяет вашу прогу на сайт. И даёт вам лишь жалкий файлик с расширением ".application" через который вы обречены каждый раз выкачивать свою программу. Конечно тут есть и плюсы: у пользователя всегда самая последняя прога. Все dll'ки не выкачиваются, а подгружаются по мере надобности.


Вы похоже плохо разобрались с технологией ClickOnce.

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

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

Ответить

Номер ответа: 6
Автор ответа:
 B-Studio



Вопросов: 0
Ответов: 5
 Профиль | | #6 Добавлено: 03.11.10 14:31
Эй, умник.. Твой код, конечно впечатляет.. я написал почти такой же на VB.NET (потом твой увидел)

wc.DownloadFile(fileblowfile, file);

А ЧТО ЕСЛИ .EXE весит >6 Mb ?!

Я написал на этот случай такой код:
Private WithEvents webClient As New System.Net.WebClient

Private Sub DownloadFile()
   webClient.DownloadFileAsync(New Uri("ftp://USERNAME:PASSWORD@ftp.HOST.org/PROGRAM.EXE";), CurDir() & "\PROGRAM.exe";)
End Sub

Private Sub webClient_DownloadProgressChanged(ByVal sender As System.Object, ByVal e As System.Net.DownloadProgressChangedEventArgs) Handles webClient.DownloadProgressChanged
   ProgressBar1.Value = e.ProgressPercentage
End Sub


У меня система основана на обновлении основной проги с помощью рядом лежащей (кусок которой приведён выше). Т.е. основная прога только проверяет, есть ли обновления (кстати, почти также, как у тебя, Mozgoed, только покруче (у меня в шестнадцатиричном виде)). А если есть, то уже вызывает обновляльщика.

Но вот только обновляльщик очень-очень медленно качает и прогрессбар не движется, хотя должен.

ПОМОГАЙТЕ.

Ответить

Номер ответа: 7
Автор ответа:
 B-Studio



Вопросов: 0
Ответов: 5
 Профиль | | #7 Добавлено: 03.11.10 14:36
Кстати, чтоб ничего не мелькало, как говорит Mozgoed, можно, чтоб прога генерировала не bat-ник, а vbs (Visual Basic Script).. Но проблема в том, что не на абсолютно любом компе эти скрипты работают. (я сталкивался с такой фиговиной)
Не знаю с чем это связано..

Ответить

Номер ответа: 8
Автор ответа:
 B-Studio



Вопросов: 0
Ответов: 5
 Профиль | | #8 Добавлено: 03.11.10 14:37
Давайте, подключайтесь, ребят.. Тема очень даже ещё актуальная на сей день =D

Ответить

Номер ответа: 9
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #9 Добавлено: 03.11.10 15:02
без некромантии плз. последний раз тема была актуальна еще в марте, в днюху моего бати :-D
так что либо создай новую либо просто почитай.

и вообще не понятно что ты хочешь, опиши вкратце, и в новой теме

Ответить

Номер ответа: 10
Автор ответа:
 LamerOnLine



ICQ: 334781088 

Вопросов: 108
Ответов: 2822
 Профиль | | #10 Добавлено: 03.11.10 15:04
Наверное это вопрос к провайдеру.

Ответить

Номер ответа: 11
Автор ответа:
 B-Studio



Вопросов: 0
Ответов: 5
 Профиль | | #11 Добавлено: 03.11.10 15:35
Да провайдер-то вроде норм.. И остальное всё качается норм...
А вот у моего обновляльщика скорость что-то совсем маленькая.. (~3Kбайт\сек)

не понятно что ты хочешь

Я хочу, чтоб качалось быстрее и прогрессбар двигался =D
Т.к.
  1. e.BytesReceived
увеличивается (сколько байт скачано), а прогрессбар не движется.

И ещё я хотел сказать, что WebClient.DownloadFile() неприемлем для больших файлов, т.к. он блокирует весь поток (окно соответственно будет '(Не отвечать)') и у юзера может начаться паника..
Так что разумнее использовать WebClient.DownloadFileAsync()

Ответить

Номер ответа: 12
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #12 Добавлено: 03.11.10 15:46
попробуй ProgressBar1.PerformStep() .. но я подозреваю,ч то эвент не вызывается в принципе..

Ответить

Номер ответа: 13
Автор ответа:
 B-Studio



Вопросов: 0
Ответов: 5
 Профиль | | #13 Добавлено: 03.11.10 15:52
Ха-ха-ха-ха.... я же не совсем идиот, чтоб не проверить вызывается ли евент...
Эвент-то вызывается, и в евенте даже
  1. e.BytesReceived

(показывает скачанные байты) меняется.
А вот e.ProgressPercentage не меняется..
Хотя в оригинальном примере, по которому я и научился делать такую штуковину всё работает.

А уж если я сделаю PerformStep, то прогрессбар вообще уйдёт в небытие (т.к. там качать ого-го сколько) и вызовет исключение, о том что
  1. .Value
  2. 'не может быть болbше
  3. .Maximum

Ответить

Номер ответа: 14
Автор ответа:
 AgentFire



ICQ: 192496851 

Вопросов: 75
Ответов: 3178
 Профиль | | #14 Добавлено: 03.11.10 16:32
значит, во-первых, не используй ProgressPercentage, он может быть в этой эвенте для других целей, а во-вторых, ПерформСтеп не должен вызывать ничего критичного. юзай его один раз, после каждого PBProgess.Value = ...

Ответить

Номер ответа: 15
Автор ответа:
 Artyom



Разработчик

Вопросов: 130
Ответов: 6602
 Профиль | | #15 Добавлено: 03.11.10 17:57
B-Studio пишет:
А вот e.ProgressPercentage не меняется..

Как насчет варианта что сервер не отдает в заголовках размер файла, и, следовательно, нет возможности посчитать сколько % файла загружено?

А вообще-то Click Once для этих целей самое оно, а не наколенные поделки.

Ответить

Страница: 1 |

Поиск по форуму



© Copyright 2002-2011 VBNet.RU | Пишите нам