The Wiert Corner – irregular stream of stuff

Jeroen W. Pluimers on .NET, C#, Delphi, databases, and personal interests

  • My badges

  • Twitter Updates

  • My Flickr Stream

  • Pages

  • All categories

  • Enter your email address to subscribe to this blog and receive notifications of new posts by email.

    Join 2,909 other followers

Archive for the ‘Inno Setup ISS’ Category

Main Innosetup site down; downloads are now at GitHub thanks to Martijn Laan

Posted by jpluimers on 2018/06/22

Earlier this week, I wanted to install the most recent version of InnoSetup, but found out the main site at is down.

The new versions released earlier this month were on my list of things to try:

There WayBack archive editions of most directories but all of them are too old to hold the 5.6.0 or 5.6.1 versions (some do not even have the 5.5.9 version either).

In the mean time, Martijn Laan has provided the most recent binaries on GitHub:

Parallel to that, I have archived or found back the most recent versions of these pages and downloads:


Posted in Development, Inno Setup ISS, Installer-Development, Software Development | Leave a Comment »

InnoSetup where the *AppData constants point to

Posted by jpluimers on 2017/11/08

The paths are on a standard Windows 7 x64 machine installed on the C: drive. More recent versions of Windows should use the same place.

I’ve not been able to verify this in a domain situation with roaming profiles and redirected folder paths. If anyone has info on that, please let me know.

Anyway, I’ve made some the constants into a table:

Inno Setup constant
Windows 7 directory KNOWNFOLDERID
CSIDL (<= Vista)
[WayBack] ([WayBack])
Environment variable
commonappdata C:\ProgramData FOLDERID_ProgramData CSIDL_COMMON_APPDATA ALLUSERSPROFILE System.Environment.SpecialFolder.CommonApplicationData
localappdata C:\Users\<UserName>\AppData\Local FOLDERID_LocalAppData CSIDL_LOCAL_APPDATA LOCALAPPDATA System.Environment.SpecialFolder.LocalApplicationData
userappdata C:\Users\<UserName>\AppData\Roaming FOLDERID_RoamingAppData CSIDL_APPDATA APPDATA System.Environment.SpecialFolder.ApplicationData

One day I might find time to make this table more complete.

Until then, the code is somewhere around theses pieces of code:

Read the rest of this entry »

Posted in Development, Inno Setup ISS, Installer-Development, Software Development | Leave a Comment »

Some Inno Setup notes

Posted by jpluimers on 2017/08/30

While updating at a client site a hugely out of date Inno Setup directory tree and instructions combo (docs mentioning isetup-2.0.19.exe, isxsetup2.exe, istool-3.0.0.exe but using ispack-5.3.10.exe) I made a few notes:

Source files I need to figure out if the are needed, where they originally come from and which actual version should be used:

The vcredist_x86_2010.exe was actually the Visual C++ 2010 SP1 one with version 10.0.40219.1, not the RTM one with version 10.0.30319.1.

I need to figure out this error message that occurs every now and then:

ShellExecuteEx failed; code 1460.
This operation returned because the timeout period expired.

I need to catch up on many things having to do with the [Code] section:

It pays off to split your [Code] section in at least three parts:

  1. A part having the Setup event functions
  2. A part having the Pascal Scripting: Scripted Constants functions
  3. A part having your own utility functions

There is no {code:...} way of getting the value of OutputBaseFileName, but you can use

Not all places can use {code:...} expansion, so you might want to use the preprocessor ispp (which stands for Inno Setup Preprocessor).

It was a bit hard to find if/when ispp was available as that has changed over the years as it used to be a separate product. From some Inno Setup 4.x or 5.x version up, it is available in the core product, possibly enabled by default (reading Inno Setup Help – Script Format Overview I’m still not sure) but to make sure it is enabled, just add this line at the start of your script files:

#preproc ispp

With the pre-processor, you can do things ike this.

Without the pre-processor, this will fail in the [Files] section with an error containig “unknown filename prefix”:

Source: Service\{code:GetServiceExe}; DestDir: {app}; ... BeforeInstall: DoBeforeInstallForService({code:GetServiceName})

With the pre-processor, you can replace it with this:

#preproc ispp

#define cServiceExe = "SomeWeirdExeName.exe"
#define cServiceName = "SomeWeirdServiceName"


Source: Service\{#cGetServiceExe}; DestDir: {app}; ... BeforeInstall: DoBeforeInstallForService('{#cServiceName}')

If you forget the single quotes around {#cServiceName} then you get this very weird error for which Googling “Can only call function” “ExpandConstant” “within parameter lists.” will return no satisfactory results:

[Window Title]

[Main Instruction]
Compiler Error

Line 91:
Directive or parameter "BeforeInstall" expression error: Can only call function "ExpandConstant" within parameter lists.


Of course the pre-processor syntax is different from the Pascal Script syntax, so this won’t work:

#define cVersion=""

#define cOutputDir="..\Output-{#cVersion}"

It needs to be this (via Inno Setup – #define directive – how to use previously defined variable? – Stack Overflow):

#define cOutputDir="..\Output-"+cVersion

Importing Windows functions from DLLs

Now that there is both an Ansi and Unicode version of Inno Setup, lots of scripts you find on the interwebz need modification: they import ANSI versions from various DLLs but now need to check the Inno Setup Pre-Processor pre-defined variable UNICODE.

Those predefined variables are listed here: Inno Setup Preprocessor: Predefined Variables

You use it like in the CodeDll.iss example:

//importing a Windows API function, automatically choosing ANSI or Unicode (requires ISPP)
function MessageBox(hWnd: Integer; lpText, lpCaption: String; uType: Cardinal): Integer;
#ifdef UNICODE
external 'MessageBoxW@user32.dll stdcall';
external 'MessageBoxA@user32.dll stdcall';

I learned this the hard way inheriting a bunch of code that would install services and failing on one service manager call with a GetLastError code ERROR_INVALID_NAME a.k.a. 123 (0x7B). I found it was the first OpenSCManager API call but since the code did not have any error handling at all tracking that down took quite some effort that failed. It would not with the documented ERROR_ACCESS_DENIED a.k.a. 5 (0x5) and  ERROR_DATABASE_DOES_NOT_EXIST a.k.a. 1065 (0x429) codes.

Of course OpenSCManager ServicesActive 0x0000007B nor OpenSCManager Error 123 didn’t return meaningful pages.

There were some mentions of invalid registry keys but those didn’t make sense to me at that time. Only after fiddling a lot I found the ROpenSCManagerW that mentioned Unicode, the ERROR_INVALID_NAME and ERROR_SHUTDOWN_IN_PROGRESS a.k.a. 1115 (0x45B). Apparently the lpDatabaseName parameter wasn’t interpreted correctly. Thad made sense as passing the 'ServicesActive' as Unicode string where the the import uses Ansi will see the string as an alternating series of ANSI character bytes and null bytes and stop after the first S.

The fix was easy: apply the above #ifdef UNICODE logic and import the function either using W@ or A@ depending on the mode.

Later I found out the code was borrowed without attribution nor mentioning the ANSI limitation from installation – upgrading windows service using inno setup – Stack Overflow. This all the more illustrates that when you borrow code from the internet you should attribute it and ensure the limitations are mentioned near your code.


Logging involves a few things:

  1. Call the Log method: Inno Setup Help – Pascal Scripting: Log
  2. Enable logging using either
  3. Inspect the log file in your %TEMP% directory (files are named like Setup Log 2016-07-12 #001.log)
  4. Note that I wish there was a Log function with parameters similar to Format, but since the underlying Pascal Script language does not allow overloads, I tried to introduce a LogFormat function instead but found out that Pascal Script doesn’t like array of const parameters (the code below fails with an identifier expected error on the const keyword) for which I asked if I can report a bug:

function LogFormat(const AFormat: string; const AArgs: array of const): string;
Log(Format(AFormat, AArgs));

view raw


hosted with ❤ by GitHub

There is an undocumented UsingWinNT function originating from the non-NT era that is sometimes used for detecting Windows versions (2K, XP, Vista, 7, 8, 8.1, 10, etc) and for fiddling with Windows Services with or without using the ServicesActive database name.

Luckily these functions exist:

Exiting and rolling prematurely

There are various ways the interwebz suggest you to exit an Inno Setup script prematurely, but most of them do not do a proper rollback/cleanup of the install.

These are bad (don’t cleanup/rollback):

Note Abort only works in these events (thanks Iepe):


Mahris has answered a nice workaround in installer – Inno Setup: How to Abort/Terminate Setup During Install? – Stack Overflow:

Source: "MYPROG.EXE"; DestDir: "{app}"; AfterInstall: MyAfterInstall

var CancelWithoutPrompt: boolean;

function InitializeSetup(): Boolean;
  CancelWithoutPrompt := false;
  result := true;

procedure MyAfterInstall();
  (Do something)
  if BadResult then begin
    MsgBox('Should cancel because...',mbError,MB_OK)
    CancelWithoutPrompt := true;

procedure CancelButtonClick(CurPageID: Integer; var Cancel, Confirm: Boolean);
  if CurPageID=wpInstalling then
    Confirm := not CancelWithoutPrompt;

x64 versus x86

Since Inno Setup supports both Win32 and Win64, you can use it to install the right flavour of dependencies, for instance installer – Install correct version of Firebird (32bit or 64bit) with Inno Setup – Stack Overflow


Posted in Development, Encoding, Inno Setup ISS, Installer-Development, Software Development, Unicode | Leave a Comment »

%d bloggers like this: