Add files to the uninstall log

78 views
Skip to first unread message

Eivind Bakkestuen

unread,
Aug 12, 2026, 10:38:27 PMAug 12
to inno...@googlegroups.com
I would like to be able to add files installed via [code] to the uninstall log, to make sure a later uninstall can delete them.

Scenario:

- installer installs DLLs into a number of existing dev environments, via detection in [code]
- user deletes or changes dev environment location
- now [code] during uninstall can't find the leftover DLLs to remove

Due to the dynamic nature of the dev environments, it's tricky (unreliable) to use Files with {code:}.

Can't find anything in the docs that allows adding to the uninstall log. Is it possible?

Martijn Laan - Inno Setup

unread,
Aug 13, 2026, 2:42:15 AMAug 13
to inno...@googlegroups.com
Hi,

Op 13-8-2026 om 04:38 schreef Eivind Bakkestuen:
Can't find anything in the docs that allows adding to the uninstall log. Is it possible?

I don't think so. You could write your info to a custom file next to the uninstall log however?

Make sure to append to it instead of overwriting, and use a format which is both backward and forward compatible.

Use {uninstallexe} and ChangeFileExt to get the filename to use.

Greetings,
Martijn

Eivind Bakkestuen

unread,
Aug 13, 2026, 4:29:41 AMAug 13
to inno...@googlegroups.com
Sure, I know I can write an extra file to disk. Or store a list in the registry.. or... :)

Would it make sense to have functionality to do this built in? Or would it be against good installer practice?



--
You received this message because you are subscribed to the Google Groups "innosetup" group.
To unsubscribe from this group and stop receiving emails from it, send an email to innosetup+...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/innosetup/178660332983.7.1812442081395642950.1546230959%40innosetup.nl.

Martijn Laan - Inno Setup

unread,
Aug 13, 2026, 9:25:05 AMAug 13
to innosetup
Hi,

Op 13-8-2026 om 10:29 schreef Eivind Bakkestuen:
Would it make sense to have functionality to do this built in? Or would it be against good installer practice?

I'm not sure, I don't yet really understand what problem you ran into.

I rather make it so you could use a regular [Files] entry/entries for this if that was possible.

Greetings,
Martijn

Eivind Bakkestuen

unread,
Aug 13, 2026, 9:23:23 PMAug 13
to inno...@googlegroups.com
There could be many different places on the end user's disk, where the installer finds an environment to install a DLL into.

It is not known how many target directories will exist beforehand; therefore, using [Files] with DestDir and {code:...}, does not work well, as you would need one line in [Files] for each unknown directory. (Well, I couldn't find anything regarding targeting multiple directories for a single entry while scouring the docs. Perhaps there's a way I failed to find?)

To do this in [Files] I imagine there would need to be support for providing a list of directories via {code:}. I have no idea how well that would work with the design of Inno.

Does Inno accept pull requests? :)


--
You received this message because you are subscribed to the Google Groups "innosetup" group.
To unsubscribe from this group and stop receiving emails from it, send an email to innosetup+...@googlegroups.com.

Gavin Lambert

unread,
Aug 14, 2026, 12:56:36 AMAug 14
to innosetup
On Friday, August 14, 2026 at 1:23:23 PM UTC+12 Eivind Bakkestuen wrote:
There could be many different places on the end user's disk, where the installer finds an environment to install a DLL into.

It is not known how many target directories will exist beforehand; therefore, using [Files] with DestDir and {code:...}, does not work well, as you would need one line in [Files] for each unknown directory. (Well, I couldn't find anything regarding targeting multiple directories for a single entry while scouring the docs. Perhaps there's a way I failed to find?)

To do this in [Files] I imagine there would need to be support for providing a list of directories via {code:}. I have no idea how well that would work with the design of Inno.

If you have some upper bound on the number of supported directories, then you can add that number of [Files] entries with something like:

...; DestDir: {code:GetDestDir|0}; Check: HasDestDir(0)
...; DestDir: {code:GetDestDir|1}; Check: HasDestDir(1)
...; DestDir: {code:GetDestDir|2}; Check: HasDestDir(2)

(Note that GetDestDir has a String parameter while HasDestDir has an Integer parameter.  It's mildly unfortunate that code constants don't have better parameter parsing, but this is a trivial case anyway.)

You can even use ISPP to generate all of these lines rather than writing by hand, so you only need to update a single number to add more, and make your installer show a warning or error if there are too many directories found.  Though the ISPP syntax can be a bit clunky and it might be more readable just to do it manually, especially when N is small.

It's fairly unusual to need to install to so many different locations, though; the only case that springs to mind is when installing a plugin, and most people wouldn't have a huge number of side-by-side versions of the host app installed, even if the plugin itself supported a large range of versions; it'd be strange to need more than 5 entries.

Martijn Laan - Inno Setup

unread,
Aug 14, 2026, 1:18:59 AMAug 14
to innosetup
Thanks for the explanation. I haven't tested it but something like this should work?

#define MaxDirs 100

#define Idx

#sub EmitFileEntry
Source: "myfile"; DestDir: "{code:GetDestDir|{#Idx}}"; Check: HasDestDir('{#Idx}'); Flags: ignoreversion
#endsub

[Files]
#for {Idx = 0; Idx < MaxDirs; Idx++} EmitFileEntry

[Code]
const
MaxDirs = {#MaxDirs};

var
Dirs: TArrayOfString;

procedure DetectDirs;
begin
{ Detect up to MaxDirs environment directories and store them in Dirs. }
end;

function InitializeSetup: Boolean;
begin
SetLength(Dirs, 0);
DetectDirs;
Result := True;
end;

function GetDestDir(Param: String): String;
var
Index: Integer;
begin
Index := StrToIntDef(Param, -1);
if (Index >= 0) and (Index < GetArrayLength(Dirs)) then
Result := Dirs[Index]
else
Result := '';
end;

function HasDestDir(Param: String): Boolean;
begin
Result := GetDestDir(Param) <> '';
end;




-------- Original Message --------

Eivind Bakkestuen

unread,
Aug 14, 2026, 2:26:00 AMAug 14
to inno...@googlegroups.com
Thank you both for the feedback. Given zero feedback on the initial suggestion (an AddToUninstallLog()... function, which would negate the messy code), I'll be using some variant of the above. Thanks :thumbsup:

Robert van der Hulst

unread,
Aug 14, 2026, 5:38:43 AMAug 14
to innosetup
Eivind,
For situations like this, I create a CMD file during setup and place that file in the same folder as the uninstaller.
For each file or folders that I need to delete, I add an entry like 

IF EXIST "%filename%" DEL"%filename%" /f

IF EXIST "%foldername%\*.*" RD " %foldername%" /s /q

I add the EXIST clause because users could delete these files themselves, and then I do not want errors during the uninstaller.

Then I run that cmd file from the installer.
Simple, but it works great

Robert

Op donderdag 13 augustus 2026 om 04:38:27 UTC+2 schreef Eivind Bakkestuen:

Martijn Laan - Inno Setup

unread,
Aug 14, 2026, 9:41:15 AMAug 14
to innosetup
Hi,

Op 14-8-2026 om 08:25 schreef Eivind Bakkestuen:
Thank you both for the feedback. Given zero feedback on the initial suggestion (an AddToUninstallLog()... function, which would negate the messy code), I'll be using some variant of the above. Thanks :thumbsup:

I don't think I would merge a PR to add AddToUninstallLog:

In my opinion installing files from [Code] is the wrong approach here. Automatic uninstallation is not the only thing you would lose. There is much more you would need to reimplement. Some examples, besides calling AddToUninstallLog:

- Registering with Restart Manager
- RestartReplace registration as an alternative
- Retry handling, automatic and manual, including option to abort
- Repeating the decision for the remaining files
- Atomically swapping in the new file over an existing one via a temporary file, handling read only files
- Logging
- Including the extra file size (and name) into the progress bar,  Add/Remove Programs' EstimatedSize, and disk space calculations
- Handling file system redirection and extended length paths

Having to add all that would be the messy code. Leaving it out means giving up robustness users expect.

Personally I think the example I showed you is the opposite of messy, I actually think it's quite elegant how you can glue a rather specific requirement onto the built-in engine; the glue code is simple to understand and very straightforward, and the bit you actually have to implement yourself is exactly your specific requirement, and nothing more.

Greetings,
Martijn
Reply all
Reply to author
Forward
0 new messages