Проекты установщика Microsoft Visual Studio - как предоставить запрос на перезапуск MSI, выполненный с помощью Process.Start (), но без опции восстановления - PullRequest
0 голосов
/ 05 марта 2019

Проблема заключается в следующем: мой пользовательский деинсталлятор вызывается перед удалением MSI.После корректного завершения работы моего приложения он вызывает msiexec, чтобы использовать установщик Windows для удаления MSI.

Это выполняется путем выполнения чего-то вроде "msiexec / x {PRODUCT_CODE} /promptrestart".

И здесьВажно то, что если система не будет перезагружена после удаления, а затем пользователь снова установит приложение, некоторые из его файлов будут удалены после следующего перезапуска, поэтому это неприемлемо.Перезапуск требуется, однако мне нужен быстрый, автоматический и безоговорочный перезапуск, это зло, и его никогда не следует использовать.

Итак, приведенный выше вызов отображает диалоговое окно STUPID «удаление / восстановление».Я этого не хочу.Когда я использую "msiexec / x {PRODUCT_CODE} / qr / promptrestart" - тогда он удаляется удачно, однако впоследствии отказывается от повторного запуска.

Я читал о настройке свойства ARPNOREPAIR.

Ноидиотам, давшим этот ответ, было бы все равно, ГДЕ и КАК это свойство можно установить.Даже ... Где собственность принадлежит, это собственность чего?Файл MSI?

Тогда, может быть, это еще один способ добиться этого, например, вызвать запрос на перезагрузку из моего кода, но ... как?Деинсталлятор должен удалить все мои файлы до этого момента.Может быть, можно выполнить какой-то сценарий после завершения процесса удаления?

(Еще одна проблема - установщик Windows не удаляет ВСЕ файлы и каталоги, созданные моим приложением. Было бы неплохо, если бы я могвыполнить некоторый код, чтобы лучше очистить.)

ОБНОВЛЕНИЕ Я вижу 2 пути впереди: создайте сценарий для запуска после завершения удаления (например, с помощью Registry или Task Scheduler или IDK), используйтеWin32 API для изменения файла MSI, потому что AFAIK можно изменить его свойства таким образом.

Ответы [ 2 ]

0 голосов
/ 09 марта 2019

Итак, существует «некрасивый хак», который решает точную проблему:

Во-первых, нам нужен исполняемый файл, на который не влияет установщик.Это просто, мы просто копируем этот установленный exe-файл в каталог TEMP и запускаем его оттуда.

Следующим шагом является то, что файл должен ждать, пока не завершится фаза удаления.Есть несколько способов сделать это.Вы можете наблюдать за процессом установки, вы можете наблюдать за файловой системой, если основной файл программы удален.Учитывая скорость обычных операций установщика, опрос один раз в секунду является достаточно хорошим вариантом.

Следующий шаг не является обязательным - вы удаляете оставшиеся файлы, созданные приложением, пустые каталоги и т. Д.

Следующим шагом является сама перезагрузка, MessageBox.Show() из PresentationFramework нормально спрашивать пользователя, когда пользователь отвечает ОК или ДА, тогда саму перезагрузку можно выполнить разными способами, я использую ExitWindowsEx() из user32.dll, поскольку, вероятно, это msiexec вызывает внутренне.

Вот пример кода:

if (MessageBox.Show(RestartPromptMsg, "", MessageBoxButton.OKCancel, MessageBoxImage.Exclamation) == MessageBoxResult.OK) {
    NativeMethods.ExitWindowsEx(
        NativeMethods.Flags.Reboot,
        NativeMethods.Reason.MajorApplication | NativeMethods.Reason.MinorInstallation | NativeMethods.Reason.FlagPlanned
    );
}

Конечно, некоторые параметры могут быть переданы нашему специальному исполняемому файлу очистки, поэтому он может выполнять некоторые дополнительные действия, такие как пропуск перезапускаподскажите, если это действительно не требуется.

Последний шаг - удалить сам исполняемый файл.Это легко, но сложно.Опять же, я надеюсь, что мой пример кода поможет:

var cleanUpTempPath = Path.Combine(Path.GetTempPath(), CleanUpExe);
File.Copy(CleanUpPath, cleanUpTempPath, overwrite: true);
Process.Start(new ProcessStartInfo {
    FileName = "cmd",
    Arguments = $"/c (\"{cleanUpTempPath}\" -purge \"{InstallerDir}\") & (del \"{cleanUpTempPath}\")",
    UseShellExecute = false,
    CreateNoWindow = true
});

Мы используем cmd.exe специальную функцию, мощность & и ().Команды, разделенные &, выполняются при выходе из предыдущей команды.Таким образом, когда наш clen up exe завершается, он удаляется тем же экземпляром cmd, который его вызвал.Не забудьте процитировать все пути, они могут содержать пробелы.Не забудьте заключить команду с аргументами в скобки, потому что в противном случае оператор & будет рассматриваться как параметр предыдущей команды, а не cmd.exe.

. Я тестировал ее в своем большом производственном приложении, и онработает как шарм.Примеры кода не работают, когда их просто вставляют, если вы ищете полный код, просто найдите его в Google, существует множество рабочих примеров на pinvoke.net и StackOverflow.

0 голосов
/ 05 марта 2019

Вопросы : Сначала несколько вопросов.

  • Перезапустите менеджер : Вызнакомы с функцией Restart Manager MSI ?Предназначен для выключения и перезапуска приложений без перезагрузок.Я бы быстро это снял?Я думаю, что это ваше реальное решение?
  • Альтернативные инструменты MSI : Есть много доступных инструментовдля создания настроек MSI .Эта ссылка также содержит дополнительные ссылки на краткое изложение недостатков проектов установщика Visual Studio.

    ARP-апплет против MSI Dialogs : ARPNOREPAIR property устанавливается в самом MSI - в таблице свойств.Это влияет только на то, что видно в апплете Add / Remove Programs Windows (ARP = Add / Remove Programs), а не на то, что вы видите, когда ваш MSI вызывается из командной строки. Затем вы видите диалоги, определенные в самом MSI (которые можно изменить - это не совсем тривиально).

    ARP / AddАпплет удаления программ : краткий обзор этого апплета ниже:

    • Удерживайте Ключ Windows и Нажмите R .Введите: appwiz.cpl и нажмите Введите .Это открывает Add /Remove Programs Applet.
    • Выберите различные записи пакета в списке, чтобы увидеть различные настройки для ARPNOREPAIR, ARPNOMODIFY и т. Д. *

      ARP

      • Если ARPNOREPAIRустановить в таблице свойств MSI, тогда Repair entry отсутствует.
      • Если * ARPNOMODIFY установлено в таблице свойств MSI, тоChange entry отсутствует.
      • Если ARPNOREMOVE установлено в таблице свойств MSI, то Remove entry отсутствует.
    • Если установлен специальный ARPSYSTEMCOMPONENT property, то MSI будет отсутствовать в ARP вообще.

    Ссылки :

...