Inno Setup: как автоматически удалить предыдущую установленную версию?
Я использую Inno Setup для создания установщика.
Я хочу, чтобы установщик автоматически удалял предыдущую установленную версию, а не перезаписывал ее. Как я могу это сделать?
11 ответов:
вы должны быть в состоянии прочитать строку удаления из реестра, учитывая AppId (т. е. значение, которое вы использовали для
AppID
на[Setup]
раздел). Его можно найти подSoftware\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(может быть либоHKLM
илиHKCU
, так что лучше проверить оба), где{AppId}
должно быть заменено фактическим значением, которое вы использовали. ИщитеUninstallString
илиQuietUninstallString
значения и использоватьExec
функция для запуска его из вашегоInitializeSetup()
функция событие.обновление: удалил нерабочее альтернативное решение с использованием
[Run]
- запись раздела с{uninstallexe}
- спасибо всем комментаторам, которые указали на это!
я использовал следующий. Я не уверен, что это самый простой способ сделать это, но это работает.
использует
{#emit SetupSetting("AppId")}
который полагается на препроцессор установки Inno. Если вы не используете это, вырезать и вставить идентификатор приложения непосредственно.///////////////////////////////////////////////////////////////////// function GetUninstallString(): String; var sUnInstPath: String; sUnInstallString: String; begin sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1'); sUnInstallString := ''; if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString); Result := sUnInstallString; end; ///////////////////////////////////////////////////////////////////// function IsUpgrade(): Boolean; begin Result := (GetUninstallString() <> ''); end; ///////////////////////////////////////////////////////////////////// function UnInstallOldVersion(): Integer; var sUnInstallString: String; iResultCode: Integer; begin // Return Values: // 1 - uninstall string is empty // 2 - error executing the UnInstallString // 3 - successfully executed the UnInstallString // default return value Result := 0; // get the uninstall string of the old app sUnInstallString := GetUninstallString(); if sUnInstallString <> '' then begin sUnInstallString := RemoveQuotes(sUnInstallString); if Exec(sUnInstallString, '/SILENT /NORESTART /SUPPRESSMSGBOXES','', SW_HIDE, ewWaitUntilTerminated, iResultCode) then Result := 3 else Result := 2; end else Result := 1; end; ///////////////////////////////////////////////////////////////////// procedure CurStepChanged(CurStep: TSetupStep); begin if (CurStep=ssInstall) then begin if (IsUpgrade()) then begin UnInstallOldVersion(); end; end; end;
варианты
см. также это сообщение в блоге "Inno Setup Script Sample for Version Comparison" который идет на один шаг дальше, и считывает номер версии любой ранее установленной версии, и сравнивает этот номер версии с номером текущего установочного пакета.
при использовании Inno Setup нет причин удалять предыдущую версию, если эта версия не была установлена другой программой установки. В противном случае обновления обрабатываются автоматически.
Если вы " просто хотите удалить старые значки "(потому что ваши изменились / обновлены), вы можете использовать это:
; attempt to remove previous versions' icons [InstallDelete] Type: filesandordirs; Name: {group}\*;
это выполняется "в начале установки", поэтому в основном удаляет старые значки, и ваши новые все равно будут установлены там после того, как это будет полностью сделано.
Я просто делаю это с каждой установкой "в случае, если что-то изменилось" значок мудрый (все это будет переустановлено в любом случае).
ответ, предоставленный Крейгом Маккуином, полностью жизнеспособен. Хотя, я бы добавил Эти комментарии:
- The
{#emit SetupSetting("AppId")}
код не работает для меня, поэтому я просто добавить мой ID приложения.- Я не хотел выполнять свою программу удаления, потому что у меня есть файл конфигурации INI, хранящийся в папке AppData/, которая удаляется деинсталлятором, и я не хочу, чтобы он был удален при установке новой версии. Итак, я немного изменил код, предоставленный Крейгом Маккуином, чтобы удалить каталог, в котором установлена программа, после получения ее пути.
Итак, что касается кода Крейга Маккуина, изменения:
- извлечь
InstallLocation
ключ вместоUninstallString
ключ.- использовать вместо
Exec(sUnInstallString, ...)
Я получил отредактированный @ Crain Mc-Queen код, я думаю, что этот код лучше, потому что не нужно изменять в другом проекте :
[Code] function GetNumber(var temp: String): Integer; var part: String; pos1: Integer; begin if Length(temp) = 0 then begin Result := -1; Exit; end; pos1 := Pos('.', temp); if (pos1 = 0) then begin Result := StrToInt(temp); temp := ''; end else begin part := Copy(temp, 1, pos1 - 1); temp := Copy(temp, pos1 + 1, Length(temp)); Result := StrToInt(part); end; end; function CompareInner(var temp1, temp2: String): Integer; var num1, num2: Integer; begin num1 := GetNumber(temp1); num2 := GetNumber(temp2); if (num1 = -1) or (num2 = -1) then begin Result := 0; Exit; end; if (num1 > num2) then begin Result := 1; end else if (num1 < num2) then begin Result := -1; end else begin Result := CompareInner(temp1, temp2); end; end; function CompareVersion(str1, str2: String): Integer; var temp1, temp2: String; begin temp1 := str1; temp2 := str2; Result := CompareInner(temp1, temp2); end; function InitializeSetup(): Boolean; var oldVersion: String; uninstaller: String; ErrorCode: Integer; vCurID :String; vCurAppName :String; begin vCurID:= '{#SetupSetting("AppId")}'; vCurAppName:= '{#SetupSetting("AppName")}'; //remove first "{" of ID vCurID:= Copy(vCurID, 2, Length(vCurID) - 1); // if RegKeyExists(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1') then begin RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1', 'DisplayVersion', oldVersion); if (CompareVersion(oldVersion, '{#SetupSetting("AppVersion")}') < 0) then begin if MsgBox('Version ' + oldVersion + ' of ' + vCurAppName + ' is already installed. Continue to use this old version?', mbConfirmation, MB_YESNO) = IDYES then begin Result := False; end else begin RegQueryStringValue(HKEY_LOCAL_MACHINE, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + vCurID + '_is1', 'UninstallString', uninstaller); ShellExec('runas', uninstaller, '/SILENT', '', SW_HIDE, ewWaitUntilTerminated, ErrorCode); Result := True; end; end else begin MsgBox('Version ' + oldVersion + ' of ' + vCurAppName + ' is already installed. This installer will exit.', mbInformation, MB_OK); Result := False; end; end else begin Result := True; end; end;
вы можете выполнить деинсталлятор в разделе [code]. Вы должны выяснить, как получить путь к существующему деинсталлятор. Для простоты при установке моих приложений я добавляю строковое значение реестра, указывающее на папку, содержащую деинсталлятор, и просто выполняю деинсталлятор в обратном вызове InitializeWizard.
имейте в виду, что Inno setup uninstaller имена все формы uninsnn.exe, вы должны принять это во внимание в своем коде.
для всех, кто использует
GetUninstallString()
предложил выше, чтобы заставить удалить внутриCurStepChanged()
и имеет проблемы с кэшированием диска, см. ниже соответствующее решение, которое фактически ждет некоторое время после unistallation для удаления exe-файла деинсталлятора!
должно быть, я что-то упустил. Элемент new файлы копируются в целевой каталог перед удалением старой установки. затем приходит деинсталлятор удаляет их и удаляет каталог.
Не используйте раздел [Run], но [UninstallRun]. На самом деле, программа под [Run] выполняются после установка, в результате чего удалить программу сразу после установки :-| Вместо этого оценивается раздел [UninstallRun]до установки.
перейдите по этой ссылке: http://news.jrsoftware.org/news/innosetup/msg55323.html
в функции InitializeSetup () вы можете вызвать "MSIEXEC /x {your program ID}" после запроса пользователя на удаление старой старой версии