Сбой InstallShield из-за плохой деинсталляции
Я строю проект InstallShield, который выполняет [Major Upgrade][1] до существующей установки (т.е. я изменил Product Code
сохраняя Upgrade Code
).
Деинсталлятор предыдущей версии (которая уже развернута) не работает и не запускает некоторые сценарии. Само по себе это не является серьезной проблемой, поскольку все соответствующие файлы удаляются заранее.
Проблема заключается в том, что когда новый установщик пытается удалить предыдущую версию, он прерывается при сбое деинсталлятора. Я попытался установить флаг "Продолжить при ошибке" ("Мультимедиа -> Обновления ->MajorUpgrade-> Дополнительно -> Дополнительные настройки"), но безрезультатно.
Вопросы:
- Есть ли способ настроить IS для бесшумного удаления предыдущей версии?
- Если нет, могу ли я написать какое-нибудь пользовательское VB-действие, чтобы молча удалить предыдущую версию?
РЕДАКТИРОВАТЬ
Не уверен, что это актуально, но вот что не так с предыдущим деинсталлятором:
Последовательность установки включает в себя некоторые пользовательские действия. Два из них вызывают исполняемые файлы, которые в свою очередь устанавливают некоторые драйверы устройств. Очевидно, они должны запускаться только во время установки. К сожалению, предыдущий конструктор не установил условие "НЕ УДАЛИТЬ", что приводит к выполнению действий во время операции удаления. Таким образом деинсталлятор дает сбой (так как он не может найти исполняемые файлы драйвера).
3 ответа
Это скорее комментарий, чем ответ, но он стал слишком длинным для комментария.
Как правило, реальное исправление заключается в создании незначительного обновления (или небольшого исправления обновления) для "исправления" ошибки в последовательности удаления, а затем удаления продукта обычным способом (будет работать независимо от того, является ли это значительным удалением обновления или вызванным вручную удалить). Это возможно потому, что незначительное обновление не удаляет существующий продукт (пользовательские действия при сбое удаления никогда не будут выполняться), а просто обновляет продукт "на месте" (или перезаписывает его). Это позволяет вам исправить все, что было неправильно в последовательности удаления, прежде чем она будет вызвана.
Я успешно использовал этот подход много раз для исправления критических ошибок в корпоративных пакетах, в которых может быть много установленных экземпляров, а последовательность удаления не работает. Однако это не совсем тривиальная вещь, это займет время и усилия по тестированию. Обычно я также поставляю обновление в виде патча, но небольшого обновления должно быть достаточно (исправление сложно).
Самый простой подход для вашего пакета незначительных обновлений, вероятно, состоит в том, чтобы установить условие, которое всегда будет ложным при всех неудачных пользовательских действиях по удалению, чтобы они никогда не выполнялись после фактического запуска удаления. Это, очевидно, оставит "некоторый мусор" на коробке, но вы можете проигнорировать это или, что еще лучше, очистить его. Будьте осторожны с кодом очистки, поскольку он имеет тенденцию включать в себя новые ошибки, с которыми вам придется со временем справиться. Развертывание - это процесс, в котором каждый добавленный цикл выпуска, исправление ошибки и настройка открывает новые возможности для непредвиденных ошибок, которые затем добавляют новую сложность и непредсказуемость для следующего выпуска. Держите вещи как можно проще. Проще говоря: просто больше вещей, которые могут сломаться, не добавляя никакой выгоды. Определенно вычистите вещи, если есть эксплуатационные проблемы, если у вас их нет.
Я не буду вдаваться в подробности относительно того, как следует осуществить незначительное обновление. Файл справки Installshield достаточно хорош в этом вопросе и должен помочь вам добиться цели. Я бы сделал обновление, которое не делает ничего, кроме изменения условий действий по удалению.
Если у вас есть небольшое обновление, вам нужно применить его, используя соответствующую командную строку ИЛИ просто использовать файл Installshield setup.exe, чтобы сделать это за вас. Снова посмотрите файл справки Installshield (" Поведение во время выполнения для незначительных обновлений" - эта страница справки должна быть всем, что вам нужно).
Командная строка для применения незначительного обновления без оболочки setup.exe обычно:
msiexec.exe /i product.msi REINSTALLMODE=vomus REINSTALL=ALL
Добавление the v option
за REINSTALLMODE
Это очень важно, если вы устанавливаете вручную через msiexec.exe без оболочки setup.exe. Это кэширует новый MSI в системе и имеет решающее значение для корректной работы небольших обновлений, в частности, для вашей цели исправления последовательности удаления.
Документация MSDN для применения незначительных обновлений.
Изменение или удаление существующего пакета с помощью незначительного обновления - это хороший подход для исправления того, что там есть. Но обеспечение того, что это произойдет до того, как ваше серьезное обновление станет проблемой. Вы не можете интегрировать его в один пакет Basic MSI, в основном потому, что это невозможно в самом установщике Windows. Хотя вы можете добавить пользовательское действие в последовательность пользовательского интерфейса, это не будет работать для тех, кто устанавливает его без вывода сообщений. И вы ничего не можете сделать в последовательности выполнения из-за ограничений в установщике Windows.
Если вы можете использовать проект Suite/Advanced UI, теоретически вы можете поставить один exe-файл, который мог бы установить второстепенное, а затем серьезное обновление; Я не уверен, что препятствия с этим подходом; как правило, пакет не используется для установки временного пакета, как это было бы при незначительном обновлении, и при этом у него нет чистого способа автоматизации удаления пакетов во время установки.
Вот два варианта, чтобы помочь вашим пользователям получить то, что им нужно, с минимальной путаницей.
Определить, проинструктировать и прервать
ActionProperty вашего основного обновления заполнен кодом продукта соответствующих пакетов, которые присутствуют на компьютере. Как правило, это один код продукта. Если вы следуете шаблону записи ISPreventDowngrade и настраиваемому действию, вы можете использовать настраиваемое действие "ошибка" типа 19, чтобы показать сообщение и прервать основное обновление, когда присутствует более старая версия. Сообщение должно указывать пользователю либо удалить старую версию продукта перед установкой новой версии; или, альтернативно, применить незначительное обновление и затем продолжить.
Сделайте условие для настраиваемого действия как можно более конкретным; если вы знаете, что один код продукта демонстрирует такое поведение, проверьте его состояние на предмет его значения в свойстве action. Если все конкретные версии демонстрируют такое поведение (но более старые версии работают нормально), рассмотрите возможность добавления вторичного "только для обнаружения" крупного обновления и сопоставьте свое пользовательское действие со свойством действия вторичного обновления.
Примечание. Можно попытаться связать это с действием последовательности пользовательского интерфейса, которое пытается автоматизировать удаление или незначительное обновление. Но обязательно сохраняйте условия в последовательности выполнения, чтобы гарантировать, что сбои при удалении без вывода сообщений получат хорошую информацию в файлах журнала.
Попробуйте игнорировать ошибки
(К сожалению, после написания этого я перечитал, где вы сказали, что пробовали этот подход, и он не работает для вас. Поэтому вы, вероятно, вернулись к Идентификации, инструктированию и отмене, или, возможно, с использованием проекта Suite/Advanced UI project доставить вещи. Однако я оставляю это для потомков, так как считаю, что в нем содержатся хорошие предложения, чтобы избежать дополнительных проблем с использованием этой опции.)
Я не использовал это, поэтому я не знаю всех последствий его поведения и не буду его рекомендовать. Но в столбце Атрибуты таблицы обновлений есть опция, которая позволяет игнорировать сбои при удалении более старой версии. InstallShield предоставляет это на вкладке "Дополнительно" как " Продолжить при отказе".
Если вы на 100% уверены, что ваша старая версия находится в удовлетворительном состоянии, и ваша новая версия будет работать после этого, вы можете попробовать это. Я настоятельно рекомендую провести тщательный контроль качества этого подхода, включая подделку новой основной версии, чтобы дальнейшие обновления работали правильно.
Аналогично совету, который я дал в " Идентифицировать, проинструктировать и прервать", попытайтесь установить " Продолжить при отказе" для как можно меньшего количества предыдущих версий. Например, вы можете разделить свои записи Upgrade на три диапазона версий: те, которые были до проблемы (не продолжайте); затронутые проблемой (продолжение); те, которые после проблемы, то есть будущие крупные обновления (не продолжать). Это позволяет избежать скрытия любых подобных проблем, которые возникнут в будущем, так что вы можете явно выбирать, как их решать по мере их появления.
Если было только одно развертывание без этого условия, вы можете написать настраиваемое действие, в котором вы можете запустить командную строку ниже:
msiexec.exe / x {PRODUCT_CODE_OF_OLD_MSI} REMOVE = "ALL" / qn
Еще один прием, который может сработать, - это запланировать действие RemoveExistingProducts перед действием InstallInitialize, как указано здесь: Как удалить предыдущую версию в рамках установки msi?
Вы также можете написать свою собственную библиотеку MSI DLL, которая останавливает запущенные процессы перед продолжением.