18

How do I detect whether the user already installed the software and if so, how to offer the possibility of removing the old version?

I have written some lines to check that. Is that correct for now? If this is correct, then how can I let the user choose whether he wants to continue the installation or uninstall the old version?

#define UNINSTKEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\setupname_is1"

var
  uninstallPath: string;

function InitializeSetup: Boolean;
begin
  if (RegQueryStringValue(HKLM,'{#UNINSTKEY}','UninstallString',uninstallPath)) and
     (uninstallPath <> '') and (fileexists(uninstallPath)) then
  begin
    Result :=
      (MsgBox(CustomMessage('NotVerifiedVersionFound'), mbConfirmation,
              MB_YESNO or MB_DEFBUTTON2) = IDYES);
  end;
  { ... }
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
Exa
  • 4,020
  • 7
  • 43
  • 60
  • 3
    Note that there isn't normally any need to do this with an Inno based setup. The exceptions are when upgrading from a non Inno setup. Once you're using Inno then it magically handles this all for you. – Deanna Jul 31 '12 at 12:10
  • @Deanna For my customer it is true that this software will always be installed with an inno setup. But Inno doesn't really "handle" it, does it? All it does, is just overwriting all old files. And I can generate an Uninstaller. But I want the Uninstall-functionality within my initial setup. – Exa Jul 31 '12 at 12:34
  • 1
    Inno (by default) disables any options that will cause old data to be orphaned, and installs into the same folders wheil updating names, shortcuts, etc. What exactly does it need to do that "just replacing files" doesn't cover? If you need to remove files, add a `[UninstallDelete]` section. Doing a full uninstall normally has unwanted side effects (depending on your use) – Deanna Jul 31 '12 at 14:49

2 Answers2

25

You could use Craig McQueen's solution originally posted here: InnoSetup: How to automatically uninstall previous installed version?

function GetUninstallString: string;
var
  sUnInstPath: string;
  sUnInstallString: String;
begin
  Result := '';
  sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{{A227028A-40D7-4695-8BA9-41DF6A3895C7}_is1'); { Your App GUID/ID }
  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 InitializeSetup: Boolean;
var
  V: Integer;
  iResultCode: Integer;
  sUnInstallString: string;
begin
  Result := True; { in case when no previous version is found }
  if RegValueExists(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{A227028A-40D7-4695-8BA9-41DF6A3895C7}_is1', 'UninstallString') then  { Your App GUID/ID }
  begin
    V := MsgBox(ExpandConstant('Hey! An old version of app was detected. Do you want to uninstall it?'), mbInformation, MB_YESNO); { Custom Message if App installed }
    if V = IDYES then
    begin
      sUnInstallString := GetUninstallString();
      sUnInstallString :=  RemoveQuotes(sUnInstallString);
      Exec(ExpandConstant(sUnInstallString), '', '', SW_SHOW, ewWaitUntilTerminated, iResultCode);
      Result := True; { if you want to proceed after uninstall }
      { Exit; //if you want to quit after uninstall }
    end
    else
      Result := False; { when older version present and not uninstalled }
  end;
end;
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
RobeN
  • 5,346
  • 1
  • 33
  • 50
  • Thanks this worked! I guess this question will soon be closed as a duplicate, though. Did not see the other question which has already been asked concerning this issue. – Exa Jul 31 '12 at 12:35
  • 3
    +1 Just few notes. The code won't work if the application was installed by a non-administrator (so the registry key is in `HKCU` and not `HKLM`). One can also use `{#SetupSetting("AppId")}` or preprocessor variable to avoid repeating the `AppId` in the registry key path. See my answer to [Inno Setup: How to overwrite on install but not on change?](http://stackoverflow.com/q/30566752/850848) for an example. Or the [source of this code](http://stackoverflow.com/a/2099805/850848), where the latter is covered too. – Martin Prikryl Feb 24 '16 at 13:34
  • I believe the call to the `ExpandConstant` in the `Exec` call should not be there. See also [Executing UninstallString in Inno Setup](http://stackoverflow.com/q/42222356/850848) (it shows a way to execute any `UninstallString`, even if it contains arguments). – Martin Prikryl Feb 14 '17 at 09:59
  • Is it `WOW6432Node` proof with this syntax? – Sandburg Feb 06 '19 at 14:21
  • @Sandburg basically this solution was written for default InnoSetup behavior and should be WOW6432Node proof. – RobeN Feb 06 '19 at 20:21
1

For anyone interested, I wrote a small DLL for Inno Setup 6 and newer that provides the ability to detect if an application is installed and to automatically uninstall the previous installed version based on your own criteria.

https://github.com/Bill-Stewart/UninsIS

Using the DLL you can automatically uninstall only when downgrading, only when upgrading, or either.

Bill_Stewart
  • 22,916
  • 4
  • 51
  • 62