Comments 55
Другой подход: myprogram может сама переименовать свой исполняемый файл myprogram.exe в myprogram.bak
После этого скачать обновление в файл с именем myprogram.exe.
А дальше апдейтер просто перезапустит myprogram.exe.
После этого скачать обновление в файл с именем myprogram.exe.
А дальше апдейтер просто перезапустит myprogram.exe.
0
Только лучше сначала скачать новый файл, чтобы не получилась ситуация, когда посередине загрузки, по каким-либо причинам, приложение завершается и пользователь остаётся с .bak файлов и неполным .exe, т.е. без рабочего приложения. Это в варианте, когда myprogram обновляет сама себя, без updater.exe.
+4
Конечно. Лучше сперва скачать, но это уже тонкости реализации :)
Так же возможен немного другой подход:
1. Приложение скачивает обновление и подменяет свой исполняемый файл. После чего само закрывается.
2. Резидентная программа раз в (10, 20, 30, 60, как нам удобнее) секунд проверяет наличие запущенной программы. Если не запущено, то просто запускает из заданной папки.
Получается что после апдейта и выхода, утилита запустит новую версию.
Так же возможен немного другой подход:
1. Приложение скачивает обновление и подменяет свой исполняемый файл. После чего само закрывается.
2. Резидентная программа раз в (10, 20, 30, 60, как нам удобнее) секунд проверяет наличие запущенной программы. Если не запущено, то просто запускает из заданной папки.
Получается что после апдейта и выхода, утилита запустит новую версию.
0
Поэтому для реализации мой метод и использую в приведенном виде.
Файл myprogram скачивает файл, затем запускает другой, чтобы тот сам все переименовал и вновь запустил основную программу.
Файл myprogram скачивает файл, затем запускает другой, чтобы тот сам все переименовал и вновь запустил основную программу.
0
А можно вопрос.
Как я понял из диалога, программа спокойно может заменить свой exe файл сама.
Почему нельзя сделать так:
1. Скачать новый файл.bak
2. Заменить свой экзешник.
3. Запустить обновлённый файл (при этом запустится вторая копия программы)
4. Завершиться.
Если вдруг нельзя допустить запуска 2 копий одновременно (например какие то ресурсы с монопольным доступом), то можно сделать так.
перед пунктом 3 Создать глобальный mutex «Перезагрузка», а на старте программы проверять его наличие и ждать пока он не исчезнет (породившая его программа, завершилась)
Как я понял из диалога, программа спокойно может заменить свой exe файл сама.
Почему нельзя сделать так:
1. Скачать новый файл.bak
2. Заменить свой экзешник.
3. Запустить обновлённый файл (при этом запустится вторая копия программы)
4. Завершиться.
Если вдруг нельзя допустить запуска 2 копий одновременно (например какие то ресурсы с монопольным доступом), то можно сделать так.
перед пунктом 3 Создать глобальный mutex «Перезагрузка», а на старте программы проверять его наличие и ждать пока он не исчезнет (породившая его программа, завершилась)
0
Простите, возможно я чего-то не понимаю, но оба ваших варианта попахивают каким-то адом. Причем, первый ад я узнаю — это Delphi-way. Одна только функция убиения процесса вызывает судорогу.
Зачем другая программа для перезапуска, если есть механизмы OS, которые позволяют выполнить перезапуск самого себя?
Почему-бы не реализовывать загрузку средствами OS, используя тот же BITS? Если уж решились на велосипед, пускай он будет стильным.
Зачем другая программа для перезапуска, если есть механизмы OS, которые позволяют выполнить перезапуск самого себя?
Почему-бы не реализовывать загрузку средствами OS, используя тот же BITS? Если уж решились на велосипед, пускай он будет стильным.
+5
А что с ClickOnce не так?
+8
Ну, автору хотелось свое и попроще. Только не увидел проверки на контрольную сумму. А если уж хотелось в пару строк и тривиально, можно было обойтись без апдейтера: скачать в %appdata%\%projectname%\updates\application.exe.upd, уйти в рестарт самого себя, при старте чекнуть наличие апдейта по указанному пути, скопировать + переименовать его, запустить с ключом на аннигиляцию родителя и подмену.
+2
Прочитав статью на MSDN, сделал вывод, что приложение устанавливать надо через установщик Windows в то время как указанный метод сразу заменяет файл безо всякой установки. На мой взгляд, этот метод удобней и быстрей. Хотя кому как.
-3
Установщик Windows тоже может заменять файл при апгрейде на новую версию. Также он может заменять несколько файлов и делать это внутри транзакции с возможностью отката. И еще много чего полезного. Советую покопать в сторону Windows Installer в целом и WiX Toolset в частности.
+3
Windows Installer не пройдет по причине того, что конкретный пример статьи основан на модпаке для игры и является лишь лаунчером, а установка самого модпака осуществляется другими средствами. Вряд ли пользователям будет удобно устанавливать модпак и потом дополнительно еще и лаунчер к нему — это не целесообразно.
0
Ох, с ним много что не так. Особенно доставляет, что встроенный метод CheckForDetailedUpdate для проверки новой версии после определённого числа вызовов кидает COMException из-за ошибки в реализации. Чтобы этого избежать нужно самостоятельно выкачивать манифест приложения и сверять версию программы. И таких граблей там на каждом шагу. Однако, предпочитаю доработать напильником, чем изобретать свой велосипед.
+1
ClickOnce может прижиться при развертывании в локальной сети. Как средство обновления через Интернет — он бяка.
0
Выбран не самый удачный пример на скриншоте (надеюсь, у вас сделано не так). Показывать пользователю модальное (скорее всего) информационное окно с единственной кнопкой «Ok», не оставляя выбора — не самая хорошая практика. Нужно делать всё тихо и незаметно, либо ненавязчиво предложить обновиться с возможностью сделать это как-нибудь потом, когда пользователю будет удобнее.
+1
Не поверишь — было: тихо скачиваем, тихо устанавливаем, громко перезапускаем прогу без каких-либо вопросов.
Заказчик попросил это уведомление добавить.
А по поводу выбора «обновить сейчас» или «потом» — добавлю такую кнопочку…
Заказчик попросил это уведомление добавить.
А по поводу выбора «обновить сейчас» или «потом» — добавлю такую кнопочку…
0
Можно тихо скачать, а установить при следующем запуске программы. Тогда не будет громкого неожиданного перезапуска, приводящего пользователя в недоумение.
Хотя чаще всего эту функцию реализуют так, как, например, сделано в Google Chrome или Firefox.
Хотя чаще всего эту функцию реализуют так, как, например, сделано в Google Chrome или Firefox.
0
Только подумал про Google Chrome. Хотя у них немного другой алгоритм реализован — в папку скачивается программа, а «стартер» (ака лаунчер браузера) запускает имя клиента которого является самым новым. Можно, конечно, старые файлы удалять, но вот зачем?
В плане браузерной ОС это хорошо, а в моем случае не комильфо.
В плане браузерной ОС это хорошо, а в моем случае не комильфо.
0
Сравнение версий у вас неправильное. Проблемы будут, например, при обновлении с 9.12.2 до 10.0.0. Нужно честно нарезать на части по точкам и сравнивать массивы целых чисел.
+2
А что мешает сравнивать непосредственно типы Version? Текущую получить очень просто:
А новую создать:
var myVersion = System.Reflection.Assembly.GetEntryAssembly().GetName().Version;
А новую создать:
var xmlVersionText = "9.12.2"; // for test
var version = new Version(xmlVersionText);
+1
Незнание мной стандартной библиотеки .NET, очевидно :) Здорово, что такая штука там есть, естественно, лучше использовать встроенные средства, чем городить свои.
+1
Какой ужасть.
По соглашениям винды у программы не должно быть прав на запись в свою же папку. Если это понадобилось, то нужно проверять, можем ли мы это сделать и если нет, то затребовать админских привилегий. Также невозможно заменить что-то кроме исполняемого файла, отсутствует возможность миграции настроек из старой версии в новую, неправильно сравниваются версии (замечание выше), присутствует «бег» (когда первая программа ещё не успела завершиться, но вспомогательная уже начала пытаться заменить её), нельзя отказаться от обновления и продолжить работу. Это всё так, на быстрый взгляд.
Да и вообще стиль кодирования — 3-й курс, не больше.
По соглашениям винды у программы не должно быть прав на запись в свою же папку. Если это понадобилось, то нужно проверять, можем ли мы это сделать и если нет, то затребовать админских привилегий. Также невозможно заменить что-то кроме исполняемого файла, отсутствует возможность миграции настроек из старой версии в новую, неправильно сравниваются версии (замечание выше), присутствует «бег» (когда первая программа ещё не успела завершиться, но вспомогательная уже начала пытаться заменить её), нельзя отказаться от обновления и продолжить работу. Это всё так, на быстрый взгляд.
Да и вообще стиль кодирования — 3-й курс, не больше.
+2
Зачем конвертить в Double, когда есть нормальный тип System.Version, который поддерживает сравнение?
System.Version thisVersion = new System.Version(Application.ProductVersion);
System.Version remoteVersion = new System.Version("1.0.2.37");
if (remoteVersion > thisVersion)
{
//обновляемся
}
0
ваш Double неправильно сработает на версиях «1.2» и «1.1.100», например.
0
Как говорится, век живи — век учись :)
Я новичок в данном языке (всего около года пишу), хотя уровня моих знаний вполне хватает для написания стабильных приложений, а улучшать не всегда есть время. Это жаль.
За подсказку спасибо! Сегодня потестирую.
Я новичок в данном языке (всего около года пишу), хотя уровня моих знаний вполне хватает для написания стабильных приложений, а улучшать не всегда есть время. Это жаль.
За подсказку спасибо! Сегодня потестирую.
0
Все интересно и просто. Сам использовал и пользуюсь подобным способом для простых программ (исполняемый файл и пара конфигов).
Но в случае использования более сложных программ (наборы библиотек, как своих так и сторонних и т.д.), нужно очень хорошо следить за целостностью файлов, об этом писалось выше, и такой способ неприемлем, увы.
Но в случае использования более сложных программ (наборы библиотек, как своих так и сторонних и т.д.), нужно очень хорошо следить за целостностью файлов, об этом писалось выше, и такой способ неприемлем, увы.
0
АДЪ!!!
Так нельзя!
Мало того, что вы таким способом можете не убить процесс (закрытие главного окна может не привести к завершению процесса), так ещё и повиснуть этот код может (если, наример, MainWindow будет переоткрываться после закрытия, или, например при попытке закрытия будет выдаваться MessageBox с предложением сохранить результаты работы).
Так нельзя!
Process[] myProcesses2 = Process.GetProcessesByName(process);
for (int i = 1; i < myProcesses2.Length; i++) { myProcesses2[i].Kill(); }
Мало того, что вы таким способом можете не убить процесс (закрытие главного окна может не привести к завершению процесса), так ещё и повиснуть этот код может (если, наример, MainWindow будет переоткрываться после закрытия, или, например при попытке закрытия будет выдаваться MessageBox с предложением сохранить результаты работы).
0
Чтобы окно выдавало сообщение с просьбой сохранить файлы/завершить работу, передается функция
А если именно завершить процесс, то:
И, как показала практика запуска приложения на нескольких машинах, эта функция работает.
Правда, 1 из 10 раз приложение действительно зависало, предлагая отправить отчет разработчику ОС…
myProcesses[i].CloseMainWindow();
А если именно завершить процесс, то:
myProcesses[0].Kill();
И, как показала практика запуска приложения на нескольких машинах, эта функция работает.
Правда, 1 из 10 раз приложение действительно зависало, предлагая отправить отчет разработчику ОС…
-1
>Так как версия у нас может иметь большое число, используем тип переменной double. Для сравнения версий мы удаляем все точки и конвертируем версию из строки в число (в примере получится число 10237).
Лучше сразу использовать тогда Int64. Те же 8 байт, что и в double, но уже без плавающей точки.
Лучше сразу использовать тогда Int64. Те же 8 байт, что и в double, но уже без плавающей точки.
-1
System.Version
. Если хочется написать велосипед, то нужно строки с версиями разбить по '.'
на четыре токена и сравнивать каждую пару. Но никак не Int64
и тем более double
.+1
А как Вы обновляете updater.exe?
+2
Основная программа при запуске проверяет версию updater.exe на сайте и, если найдет, скачивает. Уже после этого проверяет обновления себя самой.
Чуть не забыл: также программа обновляет (а если файлов нет — скачивает) дополнительные библиотеки, необходимые для работы ПО.
Чуть не забыл: также программа обновляет (а если файлов нет — скачивает) дополнительные библиотеки, необходимые для работы ПО.
0
Можно updater.exe запаковать в ресурсы программы. При обновлении качается обновленная версия программы, распаковывается updater.exe, дальше всё, как у автора. При запуске программы, если имеется файл updater.exe, то он удаляется.
Мне такой способ больше нравится, так как нет лишних исполняемых файлов для пользователя и есть возможность обновления (хотя и не очень оптимальная) updater.exe.
Мне такой способ больше нравится, так как нет лишних исполняемых файлов для пользователя и есть возможность обновления (хотя и не очень оптимальная) updater.exe.
0
Можно, но не особо нужно. В любом случае пользователь не сможет сам воспользоваться updater.exe, так как он работает только с определенным набором параметров (указаны в статье). Так что в конкретно моем случае размещение файла updater.exe вне ресурсов основной программы является оптимальным решение.
0
Хм. использую штатные средства MS VS для публикации проекта.
Там прямо в настройках можно указать, куда лезть за обновлениями, и как регулярно их проверять.
Там прямо в настройках можно указать, куда лезть за обновлениями, и как регулярно их проверять.
0
А теперь вы попробуйте обновить программу в папке Program Files в windows vista и старше и слегка удивитесь
0
Мсье, Вы сильно удивитесь…
Windows 7 x64. Скопировал файл в папку «c:\Program Files\myProgram\» — запустил.
Прога скачала все необходимые библиотеки с сайта, перезапустилась, нашла обновление — скачала, предложила обновиться — согласился. Обновилась, перезапустилась…
… ни единой ошибки! :)
Windows 7 x64. Скопировал файл в папку «c:\Program Files\myProgram\» — запустил.
Прога скачала все необходимые библиотеки с сайта, перезапустилась, нашла обновление — скачала, предложила обновиться — согласился. Обновилась, перезапустилась…
… ни единой ошибки! :)
0
А запуск от имени администратора что ли? Просто из-за виртуализации program files мы получали кучу проблем если запускать просто от пользователя
0
Просто от пользователя не пробовал. Я админ в системе и являюсь одной учетной записью на компе (из числа вручную созданных) при установке ОС.
Попробую сегодня запустить под обычным юзером на другой машине, сообщу о результатах.
Попробую сегодня запустить под обычным юзером на другой машине, сообщу о результатах.
0
Просто при попытке записи файлов в папке программы реально эти файлы создавались в папке Program data, и если потом запуститься от администратора или от другого пользователя их не было видно.
0
Просто от пользователя не пробовал. Я админ в системе
Windows 7 x64UAC, видимо, отключили?
0
Sign up to leave a comment.
Автоматическое обновление программ на C#