Ich verwende Inno Setup, um ein Installationsprogramm zu erstellen.
Ich möchte, dass das Installationsprogramm die zuvor installierte Version automatisch deinstalliert, anstatt sie zu überschreiben. Wie kann ich das machen?
Ich verwende Inno Setup, um ein Installationsprogramm zu erstellen.
Ich möchte, dass das Installationsprogramm die zuvor installierte Version automatisch deinstalliert, anstatt sie zu überschreiben. Wie kann ich das machen?
Antworten:
Sie sollten in der Lage sein, die Deinstallationszeichenfolge anhand der AppId (dh des Werts, für den Sie AppID
im [Setup]
Abschnitt -s verwendet haben) aus der Registrierung zu lesen . Es könnte unter Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(könnte entweder HKLM
oder sein HKCU
, also überprüfen Sie am besten beide) gefunden werden, wo {AppId}
es durch den tatsächlich verwendeten Wert ersetzt werden sollte. Suchen Sie nach den Werten UninstallString
oder QuietUninstallString
und verwenden Sie die Exec
Funktion, um sie über Ihre InitializeSetup()
Ereignisfunktion auszuführen .
Update: Nicht funktionierende alternative Lösung mit einem [Run]
-section-Eintrag mit entfernt {uninstallexe}
- danke an alle Kommentatoren, die darauf hingewiesen haben!
[Run]
Abschnittslösung funktionieren wird, da sie im Installationsprozess zu spät ausgeführt wird. Aus dem Inno Setup-Handbuch: Der Abschnitt [Ausführen] ist optional und gibt eine beliebige Anzahl von Programmen an, die ausgeführt werden sollen, nachdem das Programm erfolgreich installiert wurde, aber bevor das Setup-Programm den letzten Dialog anzeigt.
Ich habe folgendes verwendet. Ich bin mir nicht sicher, ob dies der einfachste Weg ist, aber es funktioniert.
Dies verwendet, {#emit SetupSetting("AppId")}
was auf dem Inno Setup Preprocessor beruht. Wenn Sie das nicht verwenden, schneiden Sie Ihre App-ID direkt aus und fügen Sie sie ein.
[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;
Alternativen
Siehe auch diesen Blog-Beitrag "Inno Setup Script Sample for Version Comparison", der einen Schritt weiter geht und die Versionsnummer einer zuvor installierten Version liest und diese Versionsnummer mit der des aktuellen Installationspakets vergleicht.
... 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;
Bei Verwendung von Inno Setup gibt es keinen Grund, eine frühere Version zu deinstallieren, es sei denn, diese Version wurde von einem anderen Installationsprogramm installiert. Andernfalls werden Upgrades automatisch durchgeführt.
[InstallDelete]
Abschnitt verwenden, um alte Dateien / Verzeichnisse zu entfernen. Die neuen Dateien werden dann während der Installation an den richtigen Speicherorten abgelegt.
Wenn Sie "nur die alten Symbole entfernen möchten" (weil Ihre geändert / aktualisiert wurden), können Sie Folgendes verwenden:
; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;
Dies wird "zu Beginn der Installation" ausgeführt, sodass im Grunde genommen die alten Symbole entfernt werden und Ihre neuen Symbole dort weiterhin installiert werden, nachdem dies vollständig abgeschlossen ist.
Ich mache das einfach bei jeder Installation "falls sich etwas geändert hat" symbolisch (alles wird sowieso neu installiert).
Die Antwort von Craig McQueen ist absolut realisierbar. Obwohl ich diese Kommentare hinzufügen würde:
{#emit SetupSetting("AppId")}
Code funktioniert bei mir nicht, daher füge ich einfach meine App-ID hinzu.In Bezug auf den Code von Craig McQueen gibt es folgende Änderungen:
InstallLocation
Schlüssel anstelle des abUninstallString
Schlüssels ab.DelTree
Funktion anstelle vonExec(sUnInstallString, ...)
Für alle, die die GetUninstallString()
oben vorgeschlagenen CurStepChanged()
Methoden verwenden , um eine Deinstallation im Inneren zu erzwingen, und Probleme beim Zwischenspeichern von Datenträgern auftreten, finden Sie unten eine verwandte Lösung, die nach der Deinstallation tatsächlich eine Weile auf das Löschen der Deinstallations-Exe wartet!
Sie können ein Deinstallationsprogramm im Abschnitt [Code] ausführen. Sie müssen herausfinden, wie Sie den Pfad zum vorhandenen Deinstallationsprogramm erhalten. Der Einfachheit halber füge ich bei der Installation meiner Apps einen Registrierungszeichenfolgenwert hinzu, der auf den Ordner mit dem Deinstallationsprogramm verweist, und führe das Deinstallationsprogramm einfach im InitializeWizard-Rückruf aus.
Beachten Sie, dass die Namen der Inno-Setup-Deinstallationsprogramme alle die Form uninsnnn.exe haben. Sie müssen dies in Ihrem Code berücksichtigen.
Ich habe @Crain Mc-Queen Code bearbeitet, ich denke, dieser Code ist besser, weil er nicht in einem anderen Projekt geändert werden muss:
[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;
Mir muss etwas fehlen. Die neuen Dateien werden in das Zielverzeichnis kopiert, bevor die alte Installation entfernt wird. Dann kommt das Deinstallationsprogramm, löscht sie und entfernt das Verzeichnis.
Verwenden Sie nicht den Abschnitt [Ausführen], sondern den Abschnitt [UninstallRun]. Tatsächlich wird das Programm unter [Ausführen] nach der Installation ausgeführt, wodurch Ihr Programm unmittelbar nach der Installation deinstalliert wird: - | Stattdessen wird der Abschnitt [UninstallRun] vor der Installation ausgewertet .
[UninstallRun]
ist keine Lösung für die Frage.
Folgen Sie diesem Link: http://news.jrsoftware.org/news/innosetup/msg55323.html
In der Funktion InitializeSetup () können Sie nach der Eingabeaufforderung des Benutzers "MSIEXEC / x {Ihre Programm-ID}" aufrufen, um die alte Version zu deinstallieren