#installation #nsis #uninstallation
#установка #nsis #удаление
Вопрос:
Используя NSIS, я хочу вызвать деинсталлятор ранее установленной версии из моего установщика перед установкой новой версии. Предлагаемое решение для этого заключается в выполнении следующей команды:
ExecWait '"$INSTDIRuninstall.exe" _?=$INSTDIR'
Насколько я понял, _?=$INSTDIR
это необходимо для того, чтобы сделать ExecWait
действительно ожидание. Без этого NSIS скопировала бы деинсталлятор во временный каталог, запустила бы его там, а затем вернулась бы до завершения деинсталляции. Проблема с этим решением заключается в том, что деинсталлятор выполняется непосредственно в $ INSTDIR. Это приводит к тому, что следующая команда в моем деинсталляторе завершается ошибкой:
Delete "$INSTDIRuninstall.exe"
Насколько я понял, причина, по которой uninstall.exe
не удаляется, заключается в том, что файл, который в данный момент выполняется, не может быть удален. Подводя итог моей проблеме:
ExecWait '"$INSTDIRuninstall.exe"'
не ожидает завершения деинсталляции и
ExecWait '"$INSTDIRuninstall.exe" _?=$INSTDIR'
не позволяет деинсталлятору удалять себя. Кто-нибудь знает, как дождаться завершения деинсталляции, в то же время позволяя деинсталлятору мгновенно удалять себя в процессе удаления?
Комментарии:
1. ExecWait ВСЕГДА ожидает дочернего процесса, в вашем случае этот дочерний процесс просто быстро завершается…
2. Я читал, что ExecWait ожидает только, пока деинсталлятор не будет скопирован и запущен во временном каталоге. Он определенно не ожидает завершения деинсталляции. Я протестировал это, используя некоторые окна сообщений.
3. ExecWait — это общая инструкция, и она ВСЕГДА ожидает дочернего процесса, тот факт, что выполняемая вами процедура (деинсталлятор) завершится быстро, не является ошибкой ExecWaits. ExecWait — это тонкая оболочка вокруг собственных функций CreateProcess и WaitForSingleObject…
4. Я думаю, у нас одинаковое понимание. Моей идеей было не винить ExecWait здесь. Я хотел упомянуть, что данное решение, использующее ExecWait, не выполняет то, что я ожидал от него.
Ответ №1:
_?=
Параметр сообщает деинсталлятору, что он должен не копировать себя в %temp%
и выполнять эту копию, не дожидаясь ее завершения. Путь после _?=
используется для инициализации $InstDir в деинсталляторе.
В вашем установщике вы можете сделать что-то вроде этого:
InitPluginsDir
;ReadRegStr $oldinstall ... ; Somehow detect old install
CreateDirectory "$pluginsdirunold" ; Make sure plugins do not conflict with a old uninstaller
CopyFiles /SILENT /FILESONLY "$oldinstalluninst.exe" "$pluginsdirunold"
ExecWait '"$pluginsdirunolduninst.exe" _?=$oldinstall'
Комментарии:
1. Спасибо за ответ! На самом деле я надеялся, что у вас есть идея 😉 Ваше решение выглядит блестящим. Мне потребовалось всего полчаса, чтобы понять это 🙂 Вы действительно преподнесли мне что-то новое! Дайте мне немного времени, чтобы попробовать это…
2. Хорошо, я интегрировал ваше решение в свой установщик и протестировал его. Работает отлично! Еще раз спасибо!