web-dev-qa-db-ger.com

Inno Setup: Wie deinstalliere ich eine frühere installierte Version automatisch?

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?

81
Vimvq1987

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!

25
Oliver Giesen

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 .

103
Craig McQueen

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.

7
mlaan

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).

6
rogerdpack

Die Antwort von Craig McQueen ist absolut realisierbar. Obwohl ich diese Kommentare hinzufügen würde:

  • Der {#emit SetupSetting("AppId")} Code funktioniert bei mir nicht, deshalb füge ich einfach meine App ID hinzu.
  • Ich wollte mein Deinstallationsprogramm nicht ausführen, weil ich eine INI config-Datei im Ordner AppData/gespeichert habe, die vom Deinstallationsprogramm entfernt wird, und ich möchte nicht, dass sie gelöscht wird Als ich eine neue Version installierte, änderte ich den Code von Craig McQueen ein wenig, um das Verzeichnis zu entfernen, in dem das Programm installiert ist, nachdem ich seinen Pfad abgerufen hatte.

In Bezug auf den Code von Craig McQueen ergeben sich folgende Änderungen:

  • Rufen Sie den Schlüssel InstallLocation anstelle des Schlüssels UninstallString ab.
  • Verwenden Sie die Funktion DelTree anstelle der Funktion Exec(sUnInstallString, ...)
2
user650022

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!

Disk Caching Problem mit Inno-Setup?

1
fubar

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.

0
Jim In Texas

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;
0
MohsenB