uninstaller is not created after version upgrade - inno-setup

I have setup my installer to use the code referred to in this post to check for an existing version and then calling uninstall on it before installing the new version. Works great. My problem is that after the uninstall / install steps the new versions uninstall (unins000.exe) is not created (or maybe it was but is deleted IDK). This prevents the new version from being uninstalled properly later. The uninstaller is always created if there isn't an existing version. What am I doing wrong?

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
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
if RegValueExists(HKEY_LOCAL_MACHINE,'Software\Microsoft\Windows\CurrentVersion\Uninstall\{A227028A-40D7-4695-8BA9-41DF6A3895C7}_is1', 'UninstallString') then begin
//Your App GUID/ID
V := MsgBox(ExpandConstant('{cm:YesNoUninstall}'), 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 begin
Result := False; //when older version present and not uninstalled
end;
end
else begin
Result := True; //when no previous version found
end;
end;

Related

How to verify if program is installed in system with Inno Setup Pascal Script?

I want to verify if user has Docker installed in their system.
If it is installed proceed further otherwise display an error message.
Previously I was looking at the registry group in Windows but it's not the correct way.
I want to check if cmd gives correct output for command docker.
function GetHKLM: Integer;
begin
if IsWin64 then
Result := HKLM64
else
Result := HKLM32;
end;
function GetHKU: Integer;
begin
if IsWin64 then
Result := HKCU64
else
Result := HKCU32;
end;
function InitializeSetup: Boolean;
begin
// Opening the setup installer initially
Result := True;
//if the docker is present in the machine registry return True else checking user registry
if not RegKeyExists(GetHKLM, 'SOFTWARE\Docker Inc.') then
begin
if not RegKeyExists(GetHKU, 'Software\Docker Inc.') then
begin
// return False to prevent installation to continue
Result := False;
// Display that you need to install docker.
SuppressibleMsgBox('<Docker not found!>', mbCriticalError, MB_OK, IDOK);
end;
end;
end;
How do I do this with just cmd? Instead of checking registry.. How can I run the command line and verify the output?
for etc:
function checkdocker() :Boolean;
var
dockerfound: string;
begin
Result :=
ShellExecute(application.handle, 'docker', nil, nil, SW_MAXIMIZE)
end;
function InitializeSetup: Boolean;
begin
Result := True;
if not checkdocker then;
SuppressibleMsgBox('<Docker not found!>', mbCriticalError, MB_OK, IDOK);
else
#continue
end;
To answer your literal question: Just use Exec and check the result code:
function CheckDocker: Boolean;
var
ResultCode: Integer;
begin
Result :=
Exec('docker', '', '', SW_HIDE, ewWaitUntilTerminated, ResultCode) and
(ResultCode = 0);
if Result then Log('Succeeded executing docker')
else Log('Failed to execute docker');
end;
(based on How to get an output of an Exec'ed program in Inno Setup?)
Though there's more efficient way to check if docker.exe executable is in a search path. Use FileSearch. See How can I check SQLCMD.EXE if it is installed on client in Inno Setup.

Update an InnoSetup Installation - Update Previous Install Dir

I am creating installers for either full application and patch.
For the full app installer (300MB+), versioning is x.x.0 (ex. 1.1.0).
And for the patch (10MB+) it is x.x.x (ex. 1.1.1).
The installation folder is formatted like this: "App Name ".
Example - App Name 1.1.0, App Name 1.1.1
There should only be 1 version of the app that resides in the machine, so for full version installs - when the app is detected to be previously installed, the existing app is uninstalled first.
So the scenario is like this:
User installs a full app - 1.1.0 (OK)
Directory App Name 1.1.0 is created
User installs a patch - 1.1.1 (OK)
UsePreviousAppDir=true so it writes on top of directory App Name 1.1.0
App Name 1.1.0 is renamed to App Name 1.1.1 as part of CurStepChanged() when CurStep is ssPostInstall.
User installs a full app - 1.2.0 (NOK - expected to uninstall the prev version 1.1.1 and install this new version 1.2.0)
If UsePreviousAppDir is true, directory App Name 1.1.0 is created. This is because this is what Innosetup remembers as the "previous app" (since we only renamed the patch).
If UsePreviousAppDir is false, directory App Name 1.2.0 is created. And the prev version App Name 1.1.1 is not uninstalled because the previous install was pointing to App Name 1.1.0.
How can I configure my ISS file so that when I do a full install after a patch install, it can still find the renamed directory and uninstall it?
For reference, here is my code for renaming in patch installer:
{ ///////////////////////////////////////////////////////////////////// }
procedure CurStepChanged(CurStep: TSetupStep);
begin
if (CurStep=ssPostInstall) then begin
RenameFile(ExpandConstant('{app}'), ExpandConstant('{app}\..\{#MyAppName} {#MyAppVersion}'))
end;
end;
And for my uninstall script (full version):
{ ///////////////////////////////////////////////////////////////////// }
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;
And my [UninstallDelete] section in the patch installer, in case user wants to uninstall the entire thing:
[UninstallDelete]
Type: filesandordirs; Name: "{app}\..\{#MyAppName} {#MyAppVersion}"
Thanks!

Inno Setup unzip file from input user

I try to unzip in installation file which I download from my repository. I found this code:
How to get Inno Setup to unzip a file it installed (all as part of the one installation process)
But I need to input from user in custom page about version of application in the repository, download it and try unzip. How send to value from input to ExtractMe('{tmp}\INPUT FROM USER VERSION.zip', '{app}\');
begin
{Page for input Version}
UserPage := CreateInputQueryPage(wpWelcome,
'Number of Version', 'example : 1.8.20',
'Program will download your input');
UserPage.Add('Version:', False);
UserPage.Values[0] := GetPreviousData('Version', '1.8.20');
end;
{Called when the user clicks the Next button}
function NextButtonClick(CurPageID: Integer): Boolean;
var
Version: string;
FileURL: string;
begin
if CurPageID = wpReady then
begin
Version := UserPage.Values[0];
{Download}
FileURL := Format('http://127.0.0.1/repository/ia/ats-apps/ia-client.zip/%s/ia-client.zip-%0:s.zip', [Version]); <-- FROM HERE TO BELOW
idpAddFile(FileURL, ExpandConstant(Format('{tmp}\%s.zip', [Version])));
idpDownloadAfter(wpReady);
end;
Result := True;
end;
procedure unzip(src, target: AnsiString);
external 'unzip#files:unzipper.dll stdcall delayload';
procedure ExtractMe(src, target : AnsiString);
begin
unzip(ExpandConstant(src), ExpandConstant(target));
end;
procedure CurStepChanged(CurStep: TSetupStep);
begin
if CurStep = ssPostInstall then
begin
ExtractMe('{tmp}\INPUT FROM USER VERSION.zip', '{app}\'); <--HERE
end;
end;
Thanks for tip.
The same way as you are already using in the NextButtonClick: Read the UserPage.Values[0].
ExtractMe(Format('{tmp}\%s.zip', [UserPage.Values[0]]), '{app}\');

How to show user if installer is installing or upgrading [duplicate]

This question already has answers here:
Inno Setup: How to automatically uninstall previous installed version?
(13 answers)
Closed 1 year ago.
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;
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;
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.

Uninstall when running inno setup with application already installed

I have just started using inno setup, and it seems to work well. However, when I run the installer with the app already installed it reinstalls. I would like to give the user to uninstall. Is this possible, and if so, how can it be done?
To be specific, I have written a game for a homework assignment. I made an installer using inno setup. The app installs fine and can be uninstalled using the control panel, but my professor would like to be able to uninstall the application by re-running the installer and choosing an uninstall option. This will save him time since he has about 50 of these assignments to mark.
Thanks,
Gerry
The next script will make the following options form when the application is already installed on the target system when the setup is started:
When the user clicks Repair button, the setup is normally started. When user clicks the Uninstall button, the previously installed application is uninstalled. When user closes that form, nothing happens.
Here is the script (don't forget to specify, ideally some unique, value for the AppId setup directive in your script):
[Setup]
AppName=My Program
AppVersion=1.5
AppId=1C9FAC66-219F-445B-8863-20DEAF8BB5CC
DefaultDirName={pf}\My Program
OutputDir=userdocs:Inno Setup Examples Output
[CustomMessages]
OptionsFormCaption=Setup options...
RepairButtonCaption=Repair
UninstallButtonCaption=Uninstall
[Code]
const
mrRepair = 100;
mrUninstall = 101;
function ShowOptionsForm: TModalResult;
var
OptionsForm: TSetupForm;
RepairButton: TNewButton;
UninstallButton: TNewButton;
begin
Result := mrNone;
OptionsForm := CreateCustomForm;
try
OptionsForm.Width := 220;
OptionsForm.Caption := ExpandConstant('{cm:OptionsFormCaption}');
OptionsForm.Position := poScreenCenter;
RepairButton := TNewButton.Create(OptionsForm);
RepairButton.Parent := OptionsForm;
RepairButton.Left := 8;
RepairButton.Top := 8;
RepairButton.Width := OptionsForm.ClientWidth - 16;
RepairButton.Caption := ExpandConstant('{cm:RepairButtonCaption}');
RepairButton.ModalResult := mrRepair;
UninstallButton := TNewButton.Create(OptionsForm);
UninstallButton.Parent := OptionsForm;
UninstallButton.Left := 8;
UninstallButton.Top := RepairButton.Top + RepairButton.Height + 8;
UninstallButton.Width := OptionsForm.ClientWidth - 16;
UninstallButton.Caption := ExpandConstant('{cm:UninstallButtonCaption}');
UninstallButton.ModalResult := mrUninstall;
OptionsForm.ClientHeight := RepairButton.Height + UninstallButton.Height + 24;
Result := OptionsForm.ShowModal;
finally
OptionsForm.Free;
end;
end;
function GetUninstallerPath: string;
var
RegKey: string;
begin
Result := '';
RegKey := Format('%s\%s_is1', ['Software\Microsoft\Windows\CurrentVersion\Uninstall',
'{#emit SetupSetting("AppId")}']);
if not RegQueryStringValue(HKEY_LOCAL_MACHINE, RegKey, 'UninstallString', Result) then
RegQueryStringValue(HKEY_CURRENT_USER, RegKey, 'UninstallString', Result);
end;
function InitializeSetup: Boolean;
var
UninstPath: string;
ResultCode: Integer;
begin
Result := True;
UninstPath := RemoveQuotes(GetUninstallerPath);
if UninstPath <> '' then
begin
case ShowOptionsForm of
mrRepair: Result := True;
mrUninstall:
begin
Result := False;
if not Exec(UninstPath, '', '', SW_SHOW, ewNoWait, ResultCode) then
MsgBox(FmtMessage(SetupMessage(msgUninstallOpenError), [UninstPath]), mbError, MB_OK);
end;
else
Result := False;
end;
end;
end;
For some reason your code
RegKey := Format('%s\%s_is1', ['Software\Microsoft\Windows\CurrentVersion\Uninstall',
'{#emit SetupSetting("AppId")}']);
returned an extra { to the _is1 value. I didn't had the time to check why or where i was wrong in my implementation,
all i confirm is that my installer works with the
RegKey := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#emit SetupSetting("AppId")}_is1');
alternate.
Hope it helps.
Thank you for the code sample.
When using Inno Setup, there's no reason to uninstall a previous version unless that version was installed by a different installer program. Otherwise upgrades are handled automatically.
Your answer is here :
InnoSetup: How to automatically uninstall previous installed version? previous-installed-version

Resources