Перезапись exe во время выполнения |
Прежде чем задать вопрос, смотрите FAQ.
Рекомендуем загрузить DRKB.
Перезапись exe во время выполнения |
Unconnected |
7.05.2011 13:24
Сообщение
#1
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Привет всем.
Делаю механизм самообновления для проги, может ли exe скачивать обнову и на лету себя ею перезаписывать? Качаю в TMemoryStream. Делал с сохранением обновления на диск, замещением и т.д., но это не очень стабильно работало. Сообщение отредактировано: Unconnected - 7.05.2011 13:25 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
IUnknown |
7.05.2011 15:23
Сообщение
#2
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Цитата может ли exe скачивать обнову и на лету себя ею перезаписывать? Размечтался... Что именно "не очень стабильно" работало у тебя, расскажешь?Кстати, лучше бы обновляемые части программы хранить в DLL. Скачал новую DLL-ку, выгрузил старую, заменил старый файл новым, загрузил новую библиотеку. С EXE-шником так не получится. В любом случае его надо будет выгружать. То есть, после того, как скачал обновление - перезапускать программу. |
Unconnected |
7.05.2011 17:43
Сообщение
#3
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
С DLL заморачиваться не хочу, не тот левел) Ну, я качал обновление в C:\windows\temp (даже не C:\, а букву диска получал), запускал его и закрывал работающий старый процесс. В обнове была пауза в несколько секунд, чтобы старый успел закрыться, и перемещение с заменой, это делал средствами cmd. Вот думаю, там потоки были работающие, а я перед уходом их не гасил, а тупо halt-ил.. может, они там как-то в памяти оставались через раз и не давали заместить exe.. процентов 30 проваленных обновлений было стабильно.
Сообщение отредактировано: Unconnected - 7.05.2011 17:43 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
IUnknown |
7.05.2011 18:33
Сообщение
#4
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Цитата Вот думаю, там потоки были работающие, а я перед уходом их не гасил Ты б делал правильно, проблем бы было меньше Цитата С DLL заморачиваться не хочу, не тот левел) В таком случае, кроме BAT-файла вариантов просто нет. Раньше были, но теперь (начиная с WinXP) они не проходят. Корректно завершай потоки - будет работать. |
IUnknown |
7.05.2011 21:02
Сообщение
#5
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
А нет. Только что попробовал еще один способ - работает. Итак: есть основная программа, и программа-обновлялка. Нет, я не предлагаю при запуске проверять, есть ли обновления, и если есть - то вытягивать. Все проще: проверяет твоя программа, которая загружена и работает.
А вот когда она обнаружила, что обновление есть, и его надо качать - она запускает обновлялку. Та сама, в автономном режиме, скачивает обновление, и как только скачала - дает сигнал основной программе, "неплохо бы завершиться" (реализация этого взаимодействия может быть любой. Я сделал так, что при запуске обновлялки ей параметром передается Handle главного окна приложения, на который потом и отсылается WM_CLOSE. Тут все зависит от твоей фантазии). Основная программа завершается (корректно, без спешки, чтоб не убивать потоки, а завершить как положено), возможно - перед закрытием основного потока дает сигнал обновлялке, возможно - просто обновлялка ждет какое-то время, убирает старый EXE-шник, подменяет его новым и запускает его. После чего ее функция закончена - она может самоликвидироваться. Я надеюсь, как сделать, чтоб EXE-файл после завершения работы самоудалился - знаешь? У Рихтера есть рецепт. Да, да, я знаю, какой вопрос ты сейчас задашь... (Показать/Скрыть)
|
Unconnected |
7.05.2011 23:44
Сообщение
#6
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
А я то думал, что память, выделенная под потоки, автоматом освобождается и распределяется после завершения процесса.. что интересно, в 100% тестов на моей вирте всё было нормально)
На данный момент у меня практически второй способ - исходный файл качает обнову, после запускает её и завершается. И скачанный заменяет старый. Непонятно, где здесь слабое место - как нужно правильно гасить свет, уходя? Или move /y не всегда срабатывает.. -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
-TarasBer- |
8.05.2011 11:14
Сообщение
#7
|
Гость |
> В обнове была пауза в несколько секунд, чтобы старый успел закрыться
Когда будешь писать многопоточные и прочие такие вещи, НИКОГДА не делай "паузу, чтобы успело сделать что-то там", всегда делай "подождать, пока не придёт сигнал, что что-то успело сделать что-то там" |
Unconnected |
8.05.2011 14:02
Сообщение
#8
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Хочешь сказать, что в моем случае после halt-а программа как бы не закрывается и не дает себя заместить?
-------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
IUnknown |
8.05.2011 15:14
Сообщение
#9
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Ты сам это сказал. Вот тут:
Цитата я качал обновление в C:\windows\temp (даже не C:\, а букву диска получал), запускал его и закрывал работающий старый процесс. В обнове была пауза в несколько секунд, чтобы старый успел закрыться, <cut> процентов 30 проваленных обновлений было стабильно. Закрывалась бы программа - не было б 30% провалов.P.S. ВременнЫе интервалы для ожидания закрытия программы - "Не наш метод" (С). Только сообщения/другие средства межпроцессного взаимодействия. |
Unconnected |
8.05.2011 16:58
Сообщение
#10
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Короче алгоритм я понял такой.. скачали новый, старый запускает его с параметром-своим хэндлом (или pid-ом, идентефикатором, в общем), и начинает аккуратно закрываться, а новый мониторит по ид-у, работает старый или нет, и когда его не станет - устанавливается, так? И что нужно ещё сделать при закрытии проги, кроме освобождения потоков (thread.free)? Глобально описанных и динамически создаваемых объектов нет.
Сообщение отредактировано: Unconnected - 8.05.2011 16:58 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
IUnknown |
8.05.2011 17:38
Сообщение
#11
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Цитата скачали новый, старый запускает его с параметром-своим хэндлом Кого это "его"? Я тебе что выше писал? Как только обновление доступно - запускается Updater, который и производит скачку. Скачал - послал сообщение твоей основной программе. Она его приняла, аккуратно, без спешки закрыла все потоки (не Halt-ами, а /Terminate + FreeOnTerminate/ или /Terminate + WaitFor/, заодно отслеживая, что нет спящих потоков), и потом, перед самым своим завершением, послала Updater-у сообщение: "Все, все потоки удалены, все файлы закрыты, я никого не держу и делаю харакири". Твой Updater, приняв это сообщение, понимает, что основная программа уже вот-вот отбросит коньки, и, выждав контрольный промежуток времени (уже все закрыто, тормозов при выходе не будет, ага, тут можно и подождать), удаляет старый EXE-шник, заменяет его новым, и запускает его на выполнение. После чего завершается сам (его EXE-файл при этом удаляется автоматически, спасибо Дж. Рихтеру). Итог: обновленная программа работает, имя EXE-шника не изменилось, установщик исчез. Все как и было.В твоем случае опять будет проблема. Скачал ты файл, запустил НОВОЕ приложение, старое закрылось. И что? Новое работает под новым именем. Чего ты добился? Нет уж, "разделяй и властвуй". Каждый делает то, что ему положено делать. Обновлялка качает обновления и занимается, собственно, его установкой, приложение ей в этом не мешает. А только помогает. |
Unconnected |
8.05.2011 17:51
Сообщение
#12
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
В смысле "Новое работает под новым именем"? После запуска оно копируется на место старого exe, с заменой. При новом обновлении повторяется всё, как встарь.. По-моему, что я описал, это то же самое, только без доп. программы.
Сообщение отредактировано: Unconnected - 8.05.2011 17:51 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
IUnknown |
8.05.2011 18:47
Сообщение
#13
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Цитата После запуска оно копируется на место старого exe, с заменой. Ты из работающей программы его запускаешь, и оно тебе на место работающей программы же и устанавливается? Ну-ну. Удачи.Без доп. программы не выйдет. |
Unconnected |
8.05.2011 18:52
Сообщение
#14
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Цитата Ты из работающей программы его запускаешь, и оно тебе на место работающей программы же и устанавливается? Ну да, говорю же, запущенное обновление мониторит, жив ли старый exe, и когда узнает, что уже закрылся, ждет несколько секунд и ставится с замещением, почему бы и нет.. -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
IUnknown |
8.05.2011 19:39
Сообщение
#15
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
Это "почему бы и нет" у тебя уже было. Ну, реализуй это, попробуй. Соберешь статистику отказов - приходи.
С отдельным приложением - все просто, как хозяйственное мыло: поскольку никакого "с замещением" делать не надо, то спокойно дожидаемся завершения головной программы, удаляем ее файл, так же спокойно сбрасываем содержимое TMemoryStream на диск под тем же именем, и перезапускаем приложение. Никаких мониторингов, пустых разбазариваний ресурсов, никаких "ух ты, опять 30% сбоев. Почему это, интересно? Может, действительно, надо было послушать, когда говорили про _несколько_ приложений?". Да ладно, делай как знаешь, мне что, надо очень переубеждать тебя? Только зачем спрашивать, если все равно изначально решил делать по-своему? |
Unconnected |
9.05.2011 2:01
Сообщение
#16
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Ок, совет понял) Закрывание
И ещё один поток создается BeginThread-ом, его гашу TerminateThread(trhNotify,0);. -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
IUnknown |
12.05.2011 9:26
Сообщение
#17
|
a.k.a. volvo877 Группа: Пользователи Сообщений: 1 013 Пол: Мужской Репутация: 627 |
У тебя, я надеюсь, не совершенно секретная разработка? Можешь исходники своей программы показать? (да знаю я, знаю, что ты на KOL пишешь, у меня Лазарус есть, там KOL работает). Может, нашли бы совместными усилиями, где поток держится, и как это исправить... Можно на почту, адрес у тебя есть...
|
Unconnected |
12.05.2011 12:32
Сообщение
#18
|
mea culpa Группа: Пользователи Сообщений: 1 372 Пол: Мужской Реальное имя: Николай Репутация: 24 |
Спасибо, но в принципе уже разобрался, сделал так (где-то нашел, что freeonTerminate:=true может мешать WaitFor-у. До этого у меня на нём вылетала ошибка №6, неверный дескриптор, как-то так).
try В самом потоке в секции finally выполняется loaderthread.terminate; И такой код в начале обновления:
Обновилось 100% (ну может без 1-2), это из 120 обновлений. На днях больший объем попробую.. Кстати, в KOL для работы с потоками достаточно так же унаследовать от TThread, как и делаю, хотя там и спецкомпонент есть. Сообщение отредактировано: Unconnected - 12.05.2011 12:35 -------------------- "Знаешь, стыдно - когда не видно, что услышал всё, что слушал.."
|
Текстовая версия | 29.04.2024 3:27 |