Delphi has had a THandle type for a long time (at least since Delphi 6) but didn’t use it consistently. I just had to check those declarations for various Delphi versions in order to get rid of compile errors or warnings in GExperts. Here is what I found:

• THandle is a type declared in the System unit.
• INVALID_HANDLE_VALUE is a constant declared in the Windows unit.
• THandleStream, declared in the Classes unit, has got a private field called FHandle
• THandleStream.Create has got an AHandle parameter

You would have thought that in all those places THandle is used, but it isn’t. Sometimes it’s DWord, sometimes it’s integer, and sometimes it’s THandle. Also, the declaration of the THandle type changed from LongWord to NativeUInt at some time. Only in Delphi XE2 and later it is consistent (but hey: Everybody keeps telling me to drop GExperts support for versions older than that, so there is an easy solution 😉 ).

Delphi Version THandle INVALID_HANDLE_VALUE FHandle AHandle
6 – 2007 LongWord DWord Integer Integer
2009 – XE LongWord DWord THandle Integer
XE2 and later NativeUInt THandle THandle THandle

So, in order to not get any compile errors or warnings I declared two different types:

type
{$IFDEF THANDLESTREAM_CREATE_HANDLE_IS_THANDLE} THandleStreamCreateHandleCast = THandle; {$ELSE}
THandleStreamCreateHandleCast = Integer;
{$ENDIF} {$IFDEF THANDLESTREAM_HANDLE_IS_THANDLE}
THandleCast = THandle;
{$ELSE} THandleCast = Integer; {$ENDIF}


Where the conditional defines are defined as follows:

{$INCLUDE 'jedi.inc'} // The following cond. defines address errors in various Delphi versions regarding the declaration // of the FHandle field of THandleStream and the corresponding Create constructor parameter: {$IFDEF DELPHI2009_UP}
// THandleStream.FHandle is declared as THandle (before that it's an Integer)
{$DEFINE THANDLESTREAM_HANDLE_IS_THANDLE} {$ENDIF}

{$IFDEF DELPHIXE2_UP} // AHandle is declared as THandle (otherwise it's an Integer) {$DEFINE THANDLESTREAM_CREATE_HANDLE_IS_THANDLE}
{\$ENDIF}


Really annoying but at least that takes care of these errors and warnings.

I just had a nasty surprise with Delphi 10.3 when trying to build a project that worked fine with previous Delphi versions. The problem turned out the text one of my pre build events wrote to the output. It contained the string “error :”. Apparently Delphi 10.3 parses the output of the build events and tries to interpret it.

Try for yourself:

• Create a batch file test.cmd with the following content:
@echo error: bla

• Add it as a pre build event to a Delphi project:
call path\to\test.cmd

• Try to compile.

If I’m right, you will get an error like:

And the Messages window will contain the following error:

[Exec Error] EXEC(1): bla


Very annoying. If this is documented, I can’t find it. I only see:

Cancel on error

Cancels the project build if a command returns a nonzero error code.