Я використовую Inno Setup для створення інсталятора.
Я хочу, щоб інсталятор автоматично видалив попередню встановлену версію, замість того, щоб перезаписати її. Як я можу це зробити?
Я використовую Inno Setup для створення інсталятора.
Я хочу, щоб інсталятор автоматично видалив попередню встановлену версію, замість того, щоб перезаписати її. Як я можу це зробити?
Відповіді:
Ви зможете прочитати рядок видалення з реєстру, враховуючи AppId (тобто значення, яке ви використовували AppID
в розділі [Setup]
-section). Його можна знайти в розділі Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(може бути або HKLM
абоHKCU
, тому краще перевірити обидва), де {AppId}
слід замінити фактичним значенням, яке ви використовували. Шукайте значення UninstallString
або QuietUninstallString
і використовуйте Exec
функцію для запуску з вашогоInitializeSetup()
функції події.
Оновлення: вилучено неробоче альтернативне рішення за допомогою [Run]
запису -section з {uninstallexe}
- дякую всім коментаторам, які вказали на це!
[Run]
вирішення розділу буде працювати, оскільки воно запізнюється в процесі встановлення. З посібника з налаштування Inno: Розділ [Запуск] є необов’язковим і вказує будь-яку кількість програм, які слід виконати після успішного встановлення програми, але до того, як програма встановлення відобразить остаточне діалогове вікно.
Я використав наступне. Я не впевнений, що це найпростіший спосіб це зробити, але він працює.
Це використовує те, {#emit SetupSetting("AppId")}
що покладається на Inno Setup Preprocessor. Якщо ви не використовуєте це, виріжте і вставте свій ідентифікатор програми безпосередньо.
[Code]
{ ///////////////////////////////////////////////////////////////////// }
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 для порівняння версій", яка йде на крок далі, читає номер версії будь-якої раніше встановленої версії та порівнює номер версії з номером поточного інсталяційного пакету.
... UserSIDs: TArrayOfString; I: Integer; ... if not RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString) then if isAdminLoggedOn() and RegGetSubkeyNames( HKEY_USERS, '', UserSIDs ) then for I := 0 to GetArrayLength( UserSIDs ) - 1 do begin if RegQueryStringValue( HKEY_USERS, UserSIDs[I] + '\' + sUnInstPath, 'UninstallString', sUnInstallString ) then break; end;
Якщо ви "просто хочете видалити старі значки" (оскільки ваші змінили / оновили), ви можете скористатися цим:
; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;
Це запускається "на початку інсталяції", таким чином, в основному видаляються старі значки, а ваші нові все одно будуть встановлені там після того, як це буде повністю зроблено.
Я просто роблю це при кожному встановленні піктограми "на випадок, якщо щось змінилося" (все це все одно переінсталюється).
Під час використання Inno Setup немає причин видаляти попередню версію, якщо ця версія не була встановлена іншою програмою встановлення. В іншому випадку оновлення обробляються автоматично.
[InstallDelete]
розділ для видалення старих файлів / каталогів. Потім нові файли будуть розміщені у правильних місцях під час інсталяції.
Відповідь Крейга Маккуїна цілком життєздатна. Хоча, я б додав ці коментарі:
{#emit SetupSetting("AppId")}
Код не працює для мене, так що я просто додати свій App ID.Отже, щодо коду Крейга Маккуїна, зміни:
InstallLocation
ключ замість UninstallString
ключа.DelTree
функцію замістьExec(sUnInstallString, ...)
Для тих, хто використовує GetUninstallString()
запропоноване вище для примусового видалення всередині CurStepChanged()
та має проблеми з кешуванням диска, дивіться нижче відповідне рішення, яке фактично чекає деякий час після видалення програми для видалення exe!
Ви можете виконати програму видалення в розділі [код]. Ви повинні зрозуміти, як отримати шлях до існуючої програми видалення. Для простоти, коли я встановлюю свої програми, я додаю значення рядка реєстру, яке вказує на папку, що містить деінсталятор, і просто виконую деінсталятор у зворотному виклику InitializeWizard.
Майте на увазі, що всі назви видалення програми встановлення Inno мають форму uninsnnn.exe, і це потрібно врахувати у коді.
я відредагував код @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;
Напевно, мені чогось не вистачає. Ці нові файли копіюються в каталог призначення до появи видалення старої установки. Потім програма видалення видаляє їх і видаляє каталог.
Не використовуйте розділ [Run], а [UninstallRun]. Фактично, програма під [Запуск] виконується після встановлення, що призводить до видалення вашої програми відразу після встановлення: - | Натомість перед встановленням перевіряється розділ [UninstallRun] .
[UninstallRun]
не є рішенням питання.
Перейдіть за цим посиланням: http://news.jrsoftware.org/news/innosetup/msg55323.html
У функції InitializeSetup () ви можете викликати "MSIEXEC / x {ваш ідентифікатор програми}" після запиту користувача, щоб видалити стару стару версію