Ожидание завершения удаления NSIS в установщике NSIS либо завершается ошибкой, либо деинсталлятор не будет удален

#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. Хорошо, я интегрировал ваше решение в свой установщик и протестировал его. Работает отлично! Еще раз спасибо!