If an application is installed using Inno Setup without Administrator privileges, its Uninstall registry entry is stored to HKCU hive of the local account running the installation.
To uninstall such installation, you have to use the same local account.
If you run the uninstaller using any other account, it won't have an access to HKCU of the original account (which did run the installer) and won't be able to remove it.
It does not matter that you run the uninstaller by a user with Administrator privileges. Inno Setup does not remember, what account did run the installation. So even Administrator won't be able to identify, what registry hive to look to for the HKCU Uninstall registry entry.
If you need to support a remote administration, you have to both install and uninstall with Administrator privileges.
If you need to keep your approach, you would have to modify the uninstaller to programmatically identify the original account and remove the Uninstall registry entry:
const
{ Can use #SetupSetting('AppId') [in curly brackets], }
{ if AppId directive is specified in [Setup] section }
AppId = 'My Program';
procedure RemoveNonAdminUninstallKeys;
var
Subkeys: TArrayOfString;
Subkey: string;
UninstallerLocation: string;
UninstallKey: string;
InstallLocation: string;
I: Integer;
begin
UninstallerLocation :=
AddBackslash(ExtractFilePath(ExpandFileName(ExpandConstant('{uninstallexe}'))));
Log(Format('Uninstalling from "%s"', [UninstallerLocation]));
RegGetSubkeyNames(HKU, '', Subkeys);
for I := 0 to GetArrayLength(Subkeys) - 1 do
begin
Subkey := Subkeys[I];
Log(Format('Testing account "%s"', [Subkey]));
UninstallKey :=
Subkey + '\Software\Microsoft\Windows\CurrentVersion\Uninstall\' +
AppId + '_is1';
{ Would be more appropriate to compare "uninstallexe" against a path }
{ in UninstallString, but that would require more complicated parsing. }
{ Using InstallLocation is easier, and safe, }
{ as long as UninstallFilesDir has its default value of "app" }
if RegQueryStringValue(HKU, UninstallKey, 'InstallLocation', InstallLocation) then
begin
InstallLocation := AddBackslash(ExpandFileName(InstallLocation));
Log(Format('Checking installation location "%s"', [InstallLocation]));
if CompareText(InstallLocation, UninstallerLocation) = 0 then
begin
Log(Format('Installation location matches, deleting Uninstall key "%s"', [
UninstallKey]));
if RegDeleteKeyIncludingSubkeys(HKU, UninstallKey) then
begin
Log(Format('Uninstall key "%s" deleted', [UninstallKey]));
end
else
begin
MsgBox(Format('Failed to delete Uninstall key "%s"', [UninstallKey]),
mbError, MB_OK);
end;
Break; { Do not try other acccounts }
end;
end;
end;
end;
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
begin
if CurUninstallStep = usPostUninstall then
begin
if IsAdminLoggedOn then
begin
Log('Administrator uninstallation, ' +
'will try to detect if uninstalling non-administrator installation');
RemoveNonAdminUninstallKeys;
end;
end;
end;