1

I have run into an interesting situation where I need to check for the existence of more than one program that exists on a machine, and then remove it if it exists prior to installing some software that I am bundling within a custom installer package made with Inno Setup. This would be piggybacking off of the work listed in the following questions:

I have found some good ideas from here. However, I am not sure how one could use this to check for the presence of multiple programs installed and then uninstall them. For example, the workflow would look something like this for the custom installer that I am trying to build:

  • Run installer of new programA, only if old programA does not exist. If old programA exists, then uninstall and resume the installation of new programA.
  • Run installer of new programB, only if old programB does not exist. If old programB exists, then uninstall and resume the installation of new programB.
  • Execute some cleanup commands, add some registry keys for the configuration of newly installed programA and newly installed programB.
  • Exit

Some people have suggested that there might be a way to use custom variables from the linked script so that you can check for and then uninstall multiple programs before installing the other bundled software. However, every time that I have tried creating new or custom variables the installer would no longer compile or other times it would not work as intended (i.e. one program would uninstall and the other would not). To this end, my question is concerned with creating these custom variables and how it could be used or extended to loop through the code instead of randomly trying to copy and paste the same set of code over and over again. I hope that this makes sense.

Community
  • 1
  • 1
John
  • 24,083
  • 5
  • 24
  • 25
  • Sorry, but I'm not sure I get what you've asked. You've mentioned you need to conditionally check if *programA* or *programB* are installed from your main setup at runtime. Then you've asked *my question is concerned with creating these custom variables and how it could be used or extended to loop through the code instead of randomly trying to copy and paste the same set of code over and over again* what seems to be the question about preprocessor. So for me it doesn't make sense. Could you specify when and where these variables should come from and what is their intention ? – TLama Aug 01 '12 at 06:20
  • 1
    There is nothing special about multiple applications, just repeat the code and alter it to check for the appropriate application. What are the other application installers written in? If Inno, there is still no need to do the uninstall first, and if they do need it, it should be in the logic for their installers, making your wrapper even simpler. – Deanna Aug 01 '12 at 09:45
  • @Deanna, so the best task for the preprocessor... Anyway OP didn't mentioned he wants to upgrade these applications, just uninstall. – TLama Aug 01 '12 at 11:18
  • 1
    @TLama I assumed by "If old programA exists, then uninstall and resume the installation of new programA." that they wanted to upgrade it. – Deanna Aug 01 '12 at 12:37
  • @Deanna, oh, I've misunderstand the points. Sorry; then my script is for nothing and it's really enough to just run both installers (if they are built in InnoSetup) and the setup will upgrade them. – TLama Aug 01 '12 at 12:40
  • @Deanna - not if new versions use different files or have new components. Update does not delete already installed components if you select different than during the first installation. If App uses components when Files are detected, it may be worth to force uninstallation first. Otherwise the installer would have to remove components that are not selected during next installations. – RobeN Aug 01 '12 at 12:53
  • @RobeN: Yes, that's the recomended way to do it. Inno is perfectly capable of removing old/redundant data during the install. Have the installer make sure everything is as they've asked for. Depending on your app, uninstalling first may cause folders, customisation, configuration, etc to be removed. – Deanna Aug 01 '12 at 13:08
  • @Deanna - and that may be the cause John wants to do it. Maybe he needs to uninstall everything from previous version of his app (files, configs, folders, regkeys, components, etc.), because new version is like Win98<>WinVista. We do not know the purpouse :-) But we can help John to achieve his goal. – RobeN Aug 01 '12 at 13:29

1 Answers1

3

I'm pretty sure that TLama or someone with experience will clean up the code, but you can use something like that for Check and Uninstall:

function GetUninstallStringA: string;
var
  sUnInstPathA: string;
  sUnInstallStringA: String;
begin
  Result := '';
  sUnInstPathA := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{{A227028A-40D7-4695-8BA9-41DF6A3895C7}_is1'); //Your AppA GUID/ID
  sUnInstallStringA := '';
  if not RegQueryStringValue(HKLM, sUnInstPathA, 'UninstallString', sUnInstallStringA) then
    RegQueryStringValue(HKCU, sUnInstPathA, 'UninstallString', sUnInstallStringA);
  Result := sUnInstallStringA;
end;

function GetUninstallStringB: string;
var
  sUnInstPathB: string;
  sUnInstallStringB: String;
begin
  Result := '';
  sUnInstPathB := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{{A227028A-40D7-4695-8BA9-41DF6A3895C8}_is1'); //Your AppB GUID/ID
  sUnInstallStringB := '';
  if not RegQueryStringValue(HKLM, sUnInstPathB, 'UninstallString', sUnInstallStringB) then
    RegQueryStringValue(HKCU, sUnInstPathB, 'UninstallString', sUnInstallStringB);
  Result := sUnInstallStringB;
end;

function IsUpgradeA: Boolean;
begin
  Result := (GetUninstallStringA <> '');
end;

function IsUpgradeB: Boolean;
begin
  Result := (GetUninstallStringB <> '');
end;

function InitializeSetup: Boolean;
var
V: Integer;
iResultCodeA, iResultCodeB: Integer;
sUnInstallStringA, sUnInstallStringB: string;
AppA, AppB: Boolean;
    begin
      Result := True; // in case when no previous versions were found
      AppA:= RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{A227028A-40D7-4695-8BA9-41DF6A3895C7}_is1'); //Your AppA GUID/ID
      AppB:= RegKeyExists(HKEY_LOCAL_MACHINE, 'Software\Microsoft\Windows\CurrentVersion\Uninstall\{A227028A-40D7-4695-8BA9-41DF6A3895C8}_is1'); //Your AppB GUID/ID
        if (AppA) and (AppB) then begin
          V := MsgBox(ExpandConstant('Hey! Old versions of Apps A and B were detected. Do you want to uninstall them?'), mbInformation, MB_YESNO); 
//Custom Message if App installed
          if V = IDYES then
          begin
            sUnInstallStringA := GetUninstallStringA;
            sUnInstallStringA :=  RemoveQuotes(sUnInstallStringA);
            Exec(ExpandConstant(sUnInstallStringA), '/silent', '', SW_SHOW, ewWaitUntilTerminated, iResultCodeA);
            sUnInstallStringB := GetUninstallStringB;
            sUnInstallStringB :=  RemoveQuotes(sUnInstallStringB);
            Exec(ExpandConstant(sUnInstallStringB), '/silent', '', SW_SHOW, ewWaitUntilTerminated, iResultCodeB);
            Result := True; //if you want to proceed after uninstall
           //Exit; //if you want to quit after uninstall
          end
          else begin
            MsgBox('You have to uninstall older versions of Apps A and B first. Installation will now be terminated.', mbInformation, MB_OK);
            Result := False; //when older versions present and not uninstalled
       end;
      end; 
          if (AppA) and (not AppB) then begin
          V := MsgBox(ExpandConstant('Hey! Old version of App A was detected. Do you want to uninstall it?'), mbInformation, MB_YESNO); 
//Custom Message if App installed
          if V = IDYES then
          begin
            sUnInstallStringA := GetUninstallStringA;
            sUnInstallStringA :=  RemoveQuotes(sUnInstallStringA);
            Exec(ExpandConstant(sUnInstallStringA), '/silent', '', SW_SHOW, ewWaitUntilTerminated, iResultCodeA);
            Result := True; //if you want to proceed after uninstall
           //Exit; //if you want to quit after uninstall
          end
          else begin
            MsgBox('You have to uninstall older version of App A first. Installation will now be terminated.', mbInformation, MB_OK);
            Result := False; //when older versions present and not uninstalled
       end;
      end;  
          if (AppB) and (not AppA) then begin
          V := MsgBox(ExpandConstant('Hey! Old version of App B was detected. Do you want to uninstall it?'), mbInformation, MB_YESNO); 
//Custom Message if App installed
          if V = IDYES then
          begin
            sUnInstallStringB := GetUninstallStringB;
            sUnInstallStringB :=  RemoveQuotes(sUnInstallStringB);
            Exec(ExpandConstant(sUnInstallStringB), '/silent', '', SW_SHOW, ewWaitUntilTerminated, iResultCodeB);
            Result := True; //if you want to proceed after uninstall
           //Exit; //if you want to quit after uninstall
          end
          else begin
            MsgBox('You have to uninstall older version of App B first. Installation will now be terminated.', mbInformation, MB_OK);
            Result := False; //when older versions present and not uninstalled
        end;
       end;
      end;

Then you can embed your new installers of AppA and AppB into this one and run them by Extracting to temp and Executing. Example:

[Files] 
Source: ".\AppA\setup_appa.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall 
Source: ".\AppB\setup_appb.exe"; DestDir: "{tmp}"; Flags: deleteafterinstall 

[Run] 
Filename: "{tmp}\setup_appa.exe"; Flags: waituntilterminated skipifdoesnotexist; StatusMsg: "Installing App A..." 
Filename: "{tmp}\setup_appa.exe"; Flags: waituntilterminated skipifdoesnotexist; StatusMsg: "Installing App A..."

Or you can write the Executing script combining [Files] and [Code] sections:

embeding installers of App A and App B:

[Files]
Source: ".\AppA\setup_appa.exe"; DestDir: "{tmp}"; Flags: dontcopy 
Source: ".\AppB\setup_appb.exe"; DestDir: "{tmp}"; Flags: dontcopy

and then calling to execute in [Code]:

[Code]

Expanding function InitializeSetup: Boolean;? Or placing elsewhere e.g. procedure CurPageChanged(CurPageID: Integer); + if CurPageID = wpInstalling then
//YOUR RUN SECTION HERE end;
with...

ExtractTemporaryFile('setup_appa.exe');
Exec(ExpandConstant('{tmp}'+'\setup_appa.exe'), '', '', SW_SHOW, ewWaitUntilTerminated, ResultCode);
RobeN
  • 5,346
  • 1
  • 33
  • 50