Ich benutze 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?
Sie sollten in der Lage sein, die Deinstallationszeichenfolge aus der Registrierung zu lesen, wenn Sie die Anwendungs-ID angeben (d. H. Den Wert, den Sie für AppID
im Abschnitt [Setup]
Verwendet haben). Sie finden es unter Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(Entweder HKLM
oder HKCU
, überprüfen Sie also am besten beide), wobei {AppId}
Durch den tatsächlich verwendeten Wert ersetzt werden sollte . Suchen Sie nach den Werten UninstallString
oder QuietUninstallString
und verwenden Sie die Funktion Exec
, um sie über Ihre Ereignisfunktion InitializeSetup()
auszuführen.
pdate: hat eine nicht funktionierende alternative Lösung mit einem [Run]
- Abschnittseintrag mit {uninstallexe}
Entfernt - danke an alle Kommentatoren, die darauf hingewiesen haben!
Ich habe folgendes benutzt. Ich bin nicht sicher, ob es der einfachste Weg ist, aber es funktioniert.
Hierfür wird {#emit SetupSetting("AppId")}
verwendet, das auf dem Inno Setup Preprocessor basiert. Wenn Sie dies nicht verwenden, fügen Sie Ihre App-ID direkt 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 dieser Blog-Beitrag "Inno Setup Script Sample für Versionsvergleich" , der einen Schritt weiter geht und die Versionsnummer einer zuvor installierten Version liest und diese Versionsnummer mit der des aktuellen Installationspakets vergleicht .
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. Ansonsten werden Upgrades automatisch abgewickelt.
Wenn Sie "nur die alten Symbole entfernen möchten" (weil Ihre geändert/aktualisiert wurden), können Sie dies verwenden:
; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;
Dies wird "zu Beginn der Installation" ausgeführt, so dass im Grunde genommen die alten Symbole entfernt werden und Ihre neuen weiterhin dort installiert werden, nachdem dies vollständig abgeschlossen ist.
Ich mache das einfach bei jeder Installation, "falls sich etwas geändert hat" (es wird sowieso alles 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, deshalb füge ich einfach meine App ID hinzu.In Bezug auf den Code von Craig McQueen ergeben sich folgende Änderungen:
InstallLocation
anstelle des Schlüssels UninstallString
ab.DelTree
anstelle der Funktion Exec(sUnInstallString, ...)
Für alle Benutzer, die die oben vorgeschlagene GetUninstallString()
verwenden, um eine Deinstallation innerhalb von CurStepChanged()
zu erzwingen, und Probleme beim Zwischenspeichern der Festplatte haben, finden Sie unten eine verwandte Lösung, die nach der Deinstallation eine Weile auf die Deinstallations-Exe wartet gelöscht werden!
Sie können ein Deinstallationsprogramm im Abschnitt [Code] ausführen. Sie müssen herausfinden, wie Sie den Pfad zum vorhandenen Deinstallationsprogramm ermitteln können. Der Einfachheit halber füge ich bei der Installation meiner Apps einen Registrierungszeichenfolgewert hinzu, der auf den Ordner verweist, der das Deinstallationsprogramm enthält, und führe das Deinstallationsprogramm einfach im Rückruf des InitializeWizard 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;