J'utilise Inno Setup pour créer un programme d'installation.
Je souhaite que le programme d'installation désinstalle automatiquement la version installée précédente, au lieu de la remplacer. Comment puis je faire ça?
Vous devriez pouvoir lire la chaîne de désinstallation à partir du registre, étant donné l'AppId (c'est-à-dire la valeur que vous avez utilisée pour AppID
dans la section [Setup]
). Il peut être trouvé sous Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(Peut être HKLM
ou HKCU
, donc mieux vérifier les deux) où {AppId}
Doit être remplacé par la valeur réelle que vous avez utilisée . Recherchez les valeurs UninstallString
ou QuietUninstallString
et utilisez la fonction Exec
pour l'exécuter à partir de votre fonction d'événement InitializeSetup()
.
Mise à jour: a supprimé la solution alternative qui ne fonctionnait pas en utilisant une entrée de section [Run]
Avec {uninstallexe}
- merci à tous les commentateurs qui l'ont signalé!
J'ai utilisé ce qui suit. Je ne suis pas sûr que ce soit la façon la plus simple de le faire, mais cela fonctionne.
Cela utilise {#emit SetupSetting("AppId")}
qui repose sur le préprocesseur Inno Setup. Si vous ne l'utilisez pas, copiez-collez directement votre ID d'application.
[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;
Alternatives
Voir aussi cet article de blog "Exemple de script de configuration Inno pour comparaison de versions" qui va plus loin et lit le numéro de version de toute version précédemment installée et compare ce numéro de version avec celui du package d'installation actuel .
Lorsque vous utilisez Inno Setup, il n'y a aucune raison de désinstaller une version précédente à moins que cette version n'ait été installée par un programme d'installation différent. Sinon, les mises à niveau sont gérées automatiquement.
Si vous "voulez simplement supprimer les anciennes icônes" (parce que les vôtres ont changé/mis à jour), vous pouvez utiliser ceci:
; attempt to remove previous versions' icons
[InstallDelete]
Type: filesandordirs; Name: {group}\*;
Ceci est exécuté "au début de l'installation", donc supprime fondamentalement les anciennes icônes, et vos nouvelles y seront toujours installées une fois que cela sera complètement fait.
Je fais juste cela avec chaque installation "au cas où quelque chose a changé" au niveau des icônes (tout est réinstallé de toute façon).
La réponse fournie par Craig McQueen est totalement viable. Cependant, j'ajouterais ces commentaires:
{#emit SetupSetting("AppId")}
ne fonctionne pas pour moi, donc j'ajoute simplement mon ID d'application.Donc, concernant le code de Craig McQueen, les changements sont:
InstallLocation
au lieu de la clé UninstallString
.DelTree
au lieu de la fonction Exec(sUnInstallString, ...)
Pour toute personne qui utilise la GetUninstallString()
suggérée ci-dessus pour forcer une désinstallation à l'intérieur de CurStepChanged()
et qui a des problèmes de mise en cache de disque, voir ci-dessous pour une solution connexe qui attend réellement un certain temps après la désinstallation pour l'exe du programme de désinstallation de être supprimé!
Vous pouvez exécuter un programme de désinstallation dans la section [code]. Vous devez comprendre comment obtenir le chemin d'accès au programme de désinstallation existant. Pour plus de simplicité lorsque j'installe mes applications, j'ajoute une valeur de chaîne de registre qui pointe vers le dossier contenant le programme de désinstallation, et j'exécute simplement le programme de désinstallation dans le rappel InitializeWizard.
Gardez à l'esprit que les noms du programme de désinstallation d'Inno sont tous sous la forme uninsnnn.exe, vous devez en tenir compte dans votre code.
j'ai édité le code @Crain Mc-Queen, je pense que ce code est meilleur car il n'est pas nécessaire de le modifier dans un projet différent:
[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;