Uninstall fails to remove registry entries [duplicate] - inno-setup

This question already has answers here:
How to prevent uninstaller elevating for Standard Windows 10 user?
(1 answer)
Workaround for 'Apps & features' in Windows 10 starting a single-user uninstaller elevated
(1 answer)
Uninstaller trouble with standard Windows user
(1 answer)
Closed 3 years ago.
I use Inno Setup to install an Access database. It adds some registry keys, mainly trusted locations, which are removed during uninstall. This has always worked when uninstalling from the Control Panel - Programs and Features. It still works this way under Windows 10. Howeverm, it does NOT work when uninstalling under Windows 10 using Settings - Apps & Features. Any idea why and how to fix this?
Oscar.
Root: HKCU; Subkey: "Software\Microsoft\Office\12.0\Access\Security\Trusted Locations\PLAMES"; valuetype: string; valuename: "Path"; valuedata: "{app}\"; Flags: createvalueifdoesntexist uninsdeletekey
Edit1. In addition to Registry Entries not being removed, the uninstall process also optionally deletes some directories. The same issue: under Windows 10 this works fine when uninstalling from the Control Panel - Programs and Features, but does not work when installing from Settings - Apps and Features. The code for optionally removing the directories:
[Code]
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
var Entry: String;
begin
//If we reached the post uninstall step (uninstall succeeded), then...
if CurUninstallStep = usPostUninstall then
begin
//Ask about uninstalling the data folder in My Documents.
if MsgBox(ExpandConstant('{cm:UninstallFolders}'), mbInformation, MB_YesNo) = idYes then
//Delete the folder.
begin
Entry := ExpandConstant('{userdocs}') + '\PlaMES Datafile\';
if DirExists(Entry) then begin
DelTree(Entry, true, true, true);
end;
end;
end;
end;
Edit2. It seems to me the issue is not in Inno Setup, but the in way Windows 10 handles uninstall. This may or may not be limited to Inno Setup as installer. Sorry if that means I tagged poorly. What I find inexplicable: (1) when uninstalling using Control Panel - Programs and Features everything works as it should, the software/database is removed, registry entires are removed, directories are removed; (2) when uninstalling using Setting - Apps & Features, the software/database is removed, but registry entries are not removed, and directories are not removed. Why? Does Windows 10 have two different uninstall methods?

Related

Read path of uninstaller from Registry and run, if existent [duplicate]

This question already has answers here:
Inno Setup: How to automatically uninstall previous installed version?
(13 answers)
Closed 9 months ago.
Problem (EDITED) In an InnoSetup script I have to uninstall another installation of my program, which has previously been installed by InnoSetup, too. Although it regards the same program in this particular case, its way of installing has changed (it was a stand-alone installation, now it became part of another program), so the usual update procedure of InnoSetup cannot take care of this situation.
I can read its "UninstallString" from the Windows Registry with a {reg:...} expression as shown below.
Although the Registry entry exists, InnoSetup tells me "Cannot execute file, CreateProcess fails with Code 87".
According to the error message the path read from the Registry is correct; if I execute exactly this path in the command window, the uninstallation works fine.
[Run]
Filename="{reg:HKLM\SOFTWARE\WOW6432\Microsoft\Windows\CurrentVersion\Uninstall\MyProg_is1,UninstallString}"; Parameters: "/silent"; Flags: skipifdoesntexist
Also, if I put that path directly into the [Run] section as "Filename=", it works.
Any ideas what I've done wrong?
This is my solution for the given situation. PrepareToInstall is a call-back function, which is automatically called by the Pascal scripting engine prior to the installation, if it exists.
[Code]
(**
* Uninstall previous stand-alone installation of a program, if present
**)
Function PrepareToInstall(var NeedsRestart: Boolean): String;
var
UninstallString: String;
ResultCode: Integer;
pgmname : String;
begin
pgmname := 'PrevProgramName';
Result := '';
if RegQueryStringValue(
HKLM32, 'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\' + pgmname + '_is1',
'UninstallString', UninstallString) then
// Strip quotation marks from the path
StringChangeEx(UninstallString, '"', '', True);
if UninstallString <> '' then
if Exec(UninstallString, '/verysilent', '', 1, ewWaitUntilTerminated, ResultCode) then
Result := ''
else
Result := 'Error executing uninstaller, Code ' + IntToStr(ResultCode);
end;

Inno setup UninstallRun and interactive process [duplicate]

I am using Inno Setup for our WinDRBD driver, which is a port of Linbit's DRBD driver from Linux to Windows (https://github.com/LINBIT/windrbd). We
are using Inno-setup for install/uninstall and it works very well.
One thing I noticed is that if the user installs the same version twice (or upgrades to a newer version, the script in the UninstallRun section is run multiple times (once for each install) later when the user chooses to uninstall the program. Is there a way to make it only once, even if the user installed several upgrades?
What I am currently using is:
[UninstallRun]
Filename: "C:\Windows\sysnative\cmd.exe"; Parameters: "/c uninstall-windrbd.cmd"; \
WorkingDir: "{app}"; Flags: runascurrentuser waituntilterminated shellexec
(note: the sysnative thing is because Inno Setup is 32-bit but the application is 64 bit, else INF install inside the script would do the wrong thing).
It is just a minor thing, we're running an INF file uninstall which
displays a message box when run the 2nd+ time. Maybe I am missing some flag?
Adding RunOnceId: "Uninstall" (where "Uninstall" is just a random tag, you can also use foobar) to the uninstall line does the trick.
So,
[UninstallRun]
Filename: "MyUninstallProgram.exe"; \
Flags: runascurrentuser waituntilterminated runhidden; \
RunOnceId: "Uninstall"
would be a way to have an uninstall program run only once, even if there are upgrades installed.

Preparing to Uninstall like Preparing to Install Page in Inno Setup

I need to check if several .exe files are running or not (which are installed by setup) and then prompt user to close them if they are running and if not cancel the uninstall process.
Is there any way to have something like Prepare page in install for uninstaller?
Or How can I implement such checking? Even a message box would be perfect also.
If it is your application, make it create a mutex. Then you can use AppMutex directive, which works even for uninstaller.
[Setup]
AppMutex=MyProgMutex
If you cannot modify the application, you need to code the check for running application in Inno Setup. You can for example use IsAppRunning function from the answer by #RRUZ to How to check with Inno Setup, if a process is running at a Windows 2008 R2 64bit? in InitializeUninstall event function.
function InitializeUninstall(): Boolean;
var
Message: string;
begin
while IsAppRunning('MyProg.exe') do
begin
Message := 'The program is running, please close it';
if MsgBox(Message, mbError, MB_OKCANCEL) = IDCANCEL then
begin
Result := False
Exit;
end;
end;
Result := True;
end;
For a similar question on installer, see:
Is it possible to check if program is already running before trying to install it? (Inno Setup)

Inno Setup - How to prevent installation when application is installed already?

I've installed my program. But if I try to install it again, it does and the program is replaced.
I saw this question Inno Setup - How to display notifying message while installing if application is already installed on the machine?
Can I create a certain registry entry so I can check it and prevent a new installation? In this question there is some related information: Skip installation in Inno Setup if other program is not installed.
You do not need to create any registry key. The installer already creates a registry key for the uninstaller. You can just check that. It's the same key, that the answer to question, you refer to, uses. But you do not need to do the check for version. Just check an existence. Also you should check both the HKEY_LOCAL_MACHINE and the HKEY_CURRENT_USER:
#define AppId "myapp"
[Setup]
AppId={#AppId}
[Code]
function InitializeSetup(): Boolean;
begin
Result := True;
if RegKeyExists(HKEY_LOCAL_MACHINE,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1') or
RegKeyExists(HKEY_CURRENT_USER,
'SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\{#AppId}_is1') then
begin
MsgBox('The application is installed already.', mbInformation, MB_OK);
Result := False;
end;
end;
Or just reuse IsUpgrade function from Can Inno Setup respond differently to a new install and an update?

Inno-Setup ask once install two times

Using InnoSetup I want to prompt a user if they wish to install an additional piece of software - think of it as a plug-in. My issue is that the additional software package I wish to install is broken up into two MSI files. I want to only prompt the user once to install the package but have each file in the [Run] section check the same value. How do I go about doing this?
[Code]
function InstallSomething:Boolean;
begin
if (MsgBox('Do you want to install something?', mbInformation, mb_YesNo) = idYes) then
Result:=True
else
Result:=False;
end;
[Run]
Filename: {sd}\Software\MyAppA.msi; Check: InstallSomething;
Filename: {sd}\Software\MyAppB.msi; Check: InstallSomething;
So the user should only get the message once but each file should install if true or skip if false.
Can you not store the result of your function call in a boolean variable and use that boolean value in your [Run] section?
It seems that this is possible after reading the following documentation: http://www.jrsoftware.org/ishelp/index.php?topic=scriptcheck

Resources