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,914 other followers

Archive for August 30th, 2017

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 »

git – List all commits (across all branches) for a given file – Stack Overflow

Posted by jpluimers on 2017/08/30

From the “short git¬†tips” department:

Try this:

git log --all -- path

Source: git РList all commits (across all branches) for a given file РStack Overflow [WayBack]


Posted in Development, DVCS - Distributed Version Control, git, Source Code Management | Leave a Comment »

%d bloggers like this: