J'utilise Inno Setup pour créer un installateur.
Je souhaite que le programme d'installation désinstalle automatiquement la version précédente installée, au lieu de l'écraser. Comment puis je faire ça?
J'utilise Inno Setup pour créer un installateur.
Je souhaite que le programme d'installation désinstalle automatiquement la version précédente installée, au lieu de l'écraser. Comment puis je faire ça?
Réponses:
Vous devriez être en mesure de lire la chaîne de désinstallation à partir du registre, étant donné l'AppId (c'est-à-dire la valeur que vous avez utilisée AppID
dans la [Setup]
section-). Il peut être trouvé sous Software\Microsoft\Windows\CurrentVersion\Uninstall\{AppId}\
(peut être l'un HKLM
ou l' autre HKCU
, alors mieux vaut 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 Exec
fonction pour l'exécuter à partir de votre InitializeSetup()
fonction d'événement.
Mise à jour: suppression de la solution alternative non fonctionnelle utilisant une [Run]
entrée -section avec {uninstallexe}
- merci à tous les commentateurs qui l'ont signalé!
[Run]
solution de section fonctionnera, car elle s'exécute trop tard dans le processus d'installation. À partir du manuel d'Inno Setup: La section [Exécuter] est facultative et spécifie un nombre quelconque de programmes à exécuter après l'installation du programme, mais avant que le programme d'installation affiche la boîte de dialogue finale.
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.
Cette utilisation {#emit SetupSetting("AppId")}
repose sur le préprocesseur Inno Setup. Si vous ne l'utilisez pas, copiez-collez votre ID d'application directement.
[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 ce billet de blog «Exemple de script d'installation Inno pour la comparaison de versions» qui va encore plus loin, 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.
... 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;
Si vous «souhaitez simplement supprimer les anciennes icônes» (parce que les vôtres ont été modifiées / mises à 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 seront toujours installées là-bas après que cela soit complètement fait.
Je fais juste cela avec chaque installation "au cas où quelque chose aurait changé" icône sage (tout est réinstallé de toute façon).
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.
[InstallDelete]
section pour supprimer les anciens fichiers / répertoires. Les nouveaux fichiers seront ensuite placés aux bons emplacements lors de l'installation.
La réponse fournie par Craig McQueen est totalement viable. Cependant, j'ajouterais ces commentaires:
{#emit SetupSetting("AppId")}
code ne fonctionne pas pour moi, alors j'ajoute simplement mon identifiant d'application.Donc, concernant le code de Craig McQueen, les changements sont:
InstallLocation
clé au lieu de la UninstallString
clé.DelTree
fonction au lieu de laExec(sUnInstallString, ...)
Pour toute personne qui utilise ce qui est GetUninstallString()
suggéré ci-dessus pour forcer une désinstallation à l'intérieur CurStepChanged()
et a des problèmes de mise en cache du disque, voir ci-dessous une solution connexe qui attend en fait un certain temps après la désinstallation pour que l'exe du programme de désinstallation soit supprimé!
Vous pouvez exécuter un programme de désinstallation dans la section [code]. Vous devez comprendre comment obtenir le chemin du 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 des programmes de désinstallation d'Inno sont tous de la forme uninsnnn.exe, vous devez en tenir compte dans votre code.
J'ai modifié 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;
J'ai dû louper quelque chose. Les nouveaux fichiers sont copiés dans le répertoire cible avant la suppression de l'ancienne installation. Puis vient le programme de désinstallation les supprime et supprime le répertoire.
N'utilisez pas la section [Exécuter], mais [UninstallRun]. En fait, les programmes sous [Exécuter] sont exécutés après l'installation, provoquant la désinstallation de votre programme immédiatement après l'installation: - | Au lieu de cela, la section [UninstallRun] est évaluée avant l'installation.
[UninstallRun]
n'est pas une solution à la question.
Suivez ce lien: http://news.jrsoftware.org/news/innosetup/msg55323.html
Dans la fonction InitializeSetup (), vous pouvez appeler "MSIEXEC / x {votre ID de programme}" après l'invite de l'utilisateur pour désinstaller l'ancienne version