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 1,861 other subscribers

Archive for the ‘Event’ Category

inheritance – Delphi: How to call inherited inherited ancestor? – Stack Overflow

Posted by jpluimers on 2021/07/15

Officially, the answer to [WayBack] inheritance – Delphi: How to call inherited inherited ancestor? – Stack Overflow is that you can’t on the language level as I explained in my answer

You can’t in a regular language way, as this would break the object oriented aspects of the language.

You can fiddle around with pointers and clever casts to do this, but before even starting to answer that: is this really what you want?

As others mentioned: your need sounds like a serious “design smell” (which is similar to code smell, but more severe.

Edit:

Going down the pointer fiddling road might save you work in the short term, and cost you weeks of work in the long term.
This makes for some good reading on that: Upstream decisions, downstream costs.

If you really want, then there is a clever hack around this by [WayBack] User kludg – Stack Overflow.

His hack is centered around understanding what what the [WayBack] System.TMethod Record essentially is:

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Delphi interface generic function – Is there a work around? – Stack Overflow

Posted by jpluimers on 2021/06/30

The documentation simply states “no”, without explaining why.

Luckily, there is [WayBack] David Heffernan at [WayBack] Delphi interface generic function – Is there a work around? – Stack Overflow

Interfaces do not support generic parameterized methods, as the compiler says.

There is no workaround because it’s a fundamental limitation. Parameterized methods in classes are implemented by adding one method per instantiation to the class. That works for classes since they are concrete, but is not viable for interfaces. That’s because interfaces are a table of functions and the size of that table cannot vary depending on which generic method instantiations happen to be present elsewhere in the code. For similar reasons, generic methods cannot be virtual or dynamic.

In any case, it’s not possible. One option is to use a class instead. I agree that this is a bind.

If you want to do it in an interface, the best you can do is:

function CastAs(const IID: TGUID): IInterface;

But you’d have to call it like this:

MyIntf := ProxyIntf.CastAs(IMyIntf) as IMyIntf;

which feels somewhat foul.

Choose your poison!

In the background, for every distinct use of generic method parameters, the compiler generates an overloaded concrete version of the method. That is possible for classes and records, but not for interfaces.

In practice, I either go for the last option, or have the interface expose a record or class type that can have the required generic method (so the compiler can generate the overloads at run-time).

All options feel somewhat ugly, so I like the comment by [WayBack] Jason:

Wish I could “Program into Your Language, Not in it” programmers.stackexchange.com/questions/2777/…

Which leads to Code Complete

[WayBack] What are the key points of Code Complete? – Software Engineering Stack Exchange answer by [WayBack] limist:

Code Complete is about software craftsmanship; it is an advanced-beginner/intermediate-level book, written for the working programmer, but it would still be very useful to someone who’s been programming for at least a year.

Thus the key points of Code Complete (2nd ed.) are nicely summarized in its Chapter 34, Themes in Software Craftsmanship. As paraphrased from my notes:

  1. Conquer Complexity: reduce the cognitive load on your mind via discipline, conventions, and abstraction.
  2. Pick Your Process: be conscious of quality from start (requirements) to finish (deployment) and beyond (maintenance).
  3. Write Programs for People First, Computers Second: code readability is hugely important for comprehensibility, review-ability, error-rate, error-correction, modifiability, and the consequent development time and quality.
  4. Program into Your Language, Not in it: think of the What? and Why? before the How?
  5. Focus Your Attention with the Help of Conventions: conventions manage complexity by providing structure where it’s needed, so that the ultimate resource – your attention – can be effectively used.
  6. Program in Terms of the Problem Domain: work at the highest level of abstraction possible; top-level code should describe the problem being solved. Distinguish OS level, programming language level, low-level implementation structures, low-level problem domain terms, and finally, high-level problem-domain terms that would make total sense to the (non-coder) user.
  7. Watch for Falling Rocks: as programming merges art and science, good judgement is vital, including heeding warning signs.
  8. Iterate, Repeatedly, Again and Again: iterate requirements, design, estimates, code, code tuning.
  9. Thou Shalt Render Software and Religion Asunder: be eclectic and willing to experiment. Don’t be an inflexible zealot, it precludes curiosity and learning. Go beyond having just a hammer in your toolbox.

But the most important take-aways are in Chapter 33, Personal Character: once you consciously seek to improve as a coder, you can and will. The fastest way to do so is to take on the the attitudes of master coders(humility, curiosity, intellectual honesty, discipline, creativity), while also practicing their habits (many good habits are listed in the book, e.g. choosing good variable/value names).

Also, the book makes clear that the gap between average and excellent in software is immense; that fact alone should drive the conscientious coder to better himself.

That’s the short of it; the long version is in the book. :) I can also send you my not-so-long, not-so-short notes if you want more details. But the book is certainly money and time well-spent, even if the writing style is tiresome at times.

Beyond Code Complete, I’d highly recommend The Pragmatic Programmer. It’s for intermediate-level programmers, nicely-written and a great mix of high, medium, and low-level advice.

There are more limitations on generics in Delphi

The documentation on limitations has not changed much since Delphi 2009.

Delphi 2009

[WayBack] Overview of Generics: Platform Requirements and Differences

Generics are supported by the Delphi for Win32 compiler.

Runtime type identification (RTTI)

In Win32, generics and methods do not have RTTI, but instantiated types do have RTTI. An instantiated type is the combination of a generic with a set of parameters.

Interface GUID

In Win32, an instantiated interface type does not have an interface GUID.

Parameterized method in interface

A parameterized method (method declared with type parameters) cannot be declared in an interface.

Instantiation timing

Instantiation is processed by the compiler. All instantiated objects are emitted into .obj files.

Dynamic instantiation

Dynamic instantiation at runtime is not supported.

Interface constraints

The Win32 interface is not a “light” interface. This means all type parameters with interface constraints always support the COM IUnknown methods _AddRef_Release and QueryInterface or inherit from TInterfacedObject. Record types cannot specify an interface constraint parameter.

Delphi 10.3 Rio

[WayBack] Overview of Generics – RAD Studio: Platform Requirements and Differences

Generics are supported by the Delphi compilers.

Run-time type identification

In Win32, generics and methods do not have run-time type information (RTTI), but instantiated types do have RTTI. An instantiated type is the combination of a generic with a set of parameters. The RTTI for methods of a class is a subset of the RTTI for that class as a whole. If a non-generic class has a generic method, that method will not be included in the RTTI generated for the class because generics are instantiated at compile time, not at run time.

Interface GUID

In Win32, an instantiated interface type does not have an interface GUID.

Parameterized method in interface

A parameterized method (method declared with type parameters) cannot be declared in an interface.

Instantiation timing

Generic types are instantiated at compile time and emitted into executables and relocatable files. Instance variables of a generic type are instantiated at run time for classes and at compile time for generic records. The RTTI for generic classes is only generated when the classes are instantiated. RTTI for instantiated classes follows just as for non-generic classes. If the generic class has a generic method, then the instantiated generic class will not have RTTI for that generic method.

Dynamic instantiation

Dynamic instantiation at run time is not supported.

Interface constraints

The Win32 interface is not a “light” interface. This means all type parameters with interface constraints always support the COM IUnknown methods _AddRef_Release, and QueryInterface or inherit from TInterfacedObject. Record types cannot specify an interface constraint parameter.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Delphi: .dproj TargetedPlatforms bit flags in main PropertyGroup, and Platform values in other elements/attributes

Posted by jpluimers on 2021/06/09

For cleanup of .dproj files, I want to know the bit flags that TargetPlatforms can have.

TL;DR: .dproj content management in Delphi is a mess

For future reference empiric values for the flags that build the TargetedPlatforms (not to be confused with PlatformTargets) element content in the main PropertyGroup of a .dproj file in a table.

This might help creating an XSD for a .dproj file (Source: Reminder to self: make a start for an XSD that validates Delphi dproj files).

Absent cells means I have no idea if the values are relevant or what they could be.

Input for those is more than welcome.

Bit# TargetedPlatforms bit flag value Platform and $(Platform)value Meaning (dropdown value of “Select Platform” dialog)
0 1 Win32 32-bit Windows
1 2 Win64 64-bit Windows
2 4
3 8
4 16
5 32
6 64
7 128
8 256
9 512
10 1024 iOSDevice64 iOS Device 64-bit
11 2048
12 4096

($Platform) values still to cover:

  • Android
  • Linux64
  • OSX32
  • iOSDevice32
  • iOSSimulator

There is only one place for TargetedPlatforms in the .dproj file: at the XPath /Project/PropertyGroup/TargetedPlatforms.

For getting the XPath, I used Notepad++ as described in my earlier blog post Getting the path of an XML node in your code editor.

It has the combined flags, so:

  • 3 means Win32 and Win64 are enabled
  • 1025 means Win32 and iOSDevice64 are enabled

The Platform value (and thus $(Platform) value) is the one used in for example these elements or attributes:

  • /Project/PropertyGroup/Platform as currently selected platform
  • /Project/PropertyGroup/@Condition as selectivity expression, for instance
    •  <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Cfg_1)'=='true') or '$(Cfg_1_Win64)'!=''">
    • <PropertyGroup Condition="('$(Platform)'=='Win64' and '$(Base)'=='true') or '$(Base_Win64)'!=''">
  • /Project/ProjectExtensions/BorlandProject/Platforms/Platform (all having for the value property with the Platform value) having a content of either True or False.
    • This allows a .dproj file to contain information for platforms that are not visible yet.

The actual values of Platform also play a role in these places:

  • /Project/PropertyGroup/Base_Win64 containing the base settings for the Win64 platform so they can be derived for the Debug or Release builds.
  • /Project/PropertyGroup/@Condition for instance <PropertyGroup Condition="'$(Base_Win64)'!=''">
  • /Project/ProjectExtensions/BorlandProject/Deployment/DeployFile/Platform/@Name for instance <Platform Name="iOSSimulator">

Even worse: there are unneeded  nodes present for bits in TargetPlatforms and /Project/ProjectExtensions/BorlandProject/Platforms/Platform being absent or having a content False for /Project/ProjectExtensions/BorlandProject/Platforms/Platform/@value other than the enabled bits in TargetPlatforms, for instance:

  • nodes matched by /Project/ProjectExtensions/BorlandProject/Deployment/DeployFile/Platform
  • nodes matched by /Project/ProjectExtensions/BorlandProject/Deployment/ProjectRoot/@Platform
  • nodes matched by /Project/ProjectExtensions/BorlandProject/Deployment/DeployClass/Platform/@Name (and the parent DeployClass subtrees)
  • nodes matched by /Project/ProjectExtensions/BorlandProject/Platforms/Platform@value

Some examples of superfluous nodes when TargetPlarforms has a value of 1 (corresponding to Platform having a value of Win32:

<ProjectRoot Platform="Android" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Linux64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="OSX32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="Win32" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="Win64" Name="$(PROJECTNAME)"/>
<ProjectRoot Platform="iOSDevice32" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="iOSDevice64" Name="$(PROJECTNAME).app"/>
<ProjectRoot Platform="iOSSimulator" Name="$(PROJECTNAME).app"/>

Also, non relevant platforms are included in this node:

<Platforms>
    <Platform value="Win32">True</Platform>
    <Platform value="Win64">False</Platform>
</Platforms>

The Deployment section is even worse; see for instance [WayBack] delphi – How manage or clean deploy section in dproj files? – Stack Overflow.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 1 Comment »

Delphi: some notes on HModule while tracking down an access violation in TRegGroups.UnregisterModuleClasses

Posted by jpluimers on 2021/06/08

Too bad the whole mechanism involving TRegGroups.UnregisterModuleClasses is not documented anywhere

It is the underlying storage to support TClassFinder, which was introduced in Delphi 6, documented on-line in Delphi 2007, documented slightly in Delphi 2009, and since Delphi 2010 only one line of documentation was added (including the unchanged “instatiated”):

  • Delphi 2007: [WayBack] TClassFinder Class

    This is class Classes.TClassFinder.

  • Delphi 2009:[WayBack] TClassFinder Class

    The TClassFinder allows the list of registered persistent classes to be retrieved. Objects instatiated from persistent classes are those that can be stored (serialised) beyond the operation of the current application.

  • Delphi 2010:[WayBack] Classes.TClassFinder – RAD Studio VCL Reference

    TClassFinder allows registered persistent classes to be retrieved.

    The TClassFinder allows the list of registered persistent classes to be retrieved. Objects instatiated from persistent classes are those that can be stored (serialised) beyond the operation of the current application.

Back to TRegGroups.UnregisterModuleClasses: it takes a HMODULE parameter and ultimately gets called through the (since Delphi 2007) on-line documented [WayBack] Classes.UnRegisterModuleClasses Function

procedure UnRegisterModuleClasses(Module: HMODULE);

Call UnRegisterModuleClasses to unregister all object classes that were registered by the module with the handle specified by the Module parameter. When a class is unregistered, it can’t be loaded or saved by the component streaming system.

After unregistering a class, its name can be reused to register another object class.

To get more context about the access violation, I used both the stack trace and a debugging watch for GetModuleName(Module) (using the [WayBack] SysUtils.GetModuleName Function).

In order to see which classes were registered by what module, I set a breakpoint at in TRegGroup.AddClass (which can be called through various code paths):

procedure TRegGroup.AddClass(AClass: TPersistentClass);
begin
  FGroupClasses.Add(AClass);
end;

HModule

That gave me the class, but I also needed the HModule for a class, so I did a windows get module of currently executing code – Google Search, giving me these links, all C/C++ related:

Here you already see some confusion: there is HINSTANCE and HMODULE. That’s a historic thing, as described by Raymond Chen in [WayBack] What is the difference between HINSTANCE and HMODULE? | The Old New Thing:

They mean the same thing today, but at one time they were quite different.
It all comes from 16-bit Windows.
In those days, a “module” represented a file on disk that had been loaded into memory, and the module “handle” was a handle to a data structure that described the parts of the file, where they come from, and where they had been loaded into memory (if at all). On the other hand an “instance” represented a “set of variables”.
One analogy that might (or might not) make sense is that a “module” is like the code for a C++ class – it describes how to construct an object, it implements the methods, it describes how the objects of the class behave. On the other hand, an “instance” is like a C++ object that belongs to that class – it describes the state of a particular instance of that object.
In C# terms, a “module” is like a “type” and an instance is like an “object”. (Except that modules don’t have things like “static members”, but it was a weak analogy anyway.)

GetModuleName

Searching for delphi “__ImageBase” – Google Search then got me [WayBack] c++ – Get DLL path at runtime – Stack Overflow with a nice Delphi related answer by [WayBack] Ian Boyd:

For Delphi users:

SysUtils.GetModuleName(hInstance);              //Works; hInstance is a special global variable
SysUtils.GetModuleName(0);                      //Fails; returns the name of the host exe process
SysUtils.GetModuleName(GetModuleFilename(nil)); //Fails; returns the name of the host exe process

In case your Delphi doesn’t have SysUtils.GetModuleName, it is declared as:

...

This reassured my use of [WayBack] SysUtils.GetModuleName code was OK:

function GetModuleName(Module: HMODULE): string; 
var
  ModName: array[0..MAX_PATH] of Char; 
begin
  SetString(Result, ModName, GetModuleFileName(Module, ModName, Length(ModName))); 
end;

HInstance in Delphi

The example from Ian Boyd also brought back memories from long ago about the [WayBack] HInstance Variable – Delphi in a Nutshell [Book]:

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, History, Software Development | Leave a Comment »

VMware ESXi: VMware Tools Installed but not running

Posted by jpluimers on 2021/06/04

Sometimes you get this situation on a Windows VM, usually after a reboot but not logging on:

Networking No network information
VMware Tools Installed but not running

“Windows” “VMware Tools” “Installed but not running” – Google Search mostly gives results about the VMware tools installation ISO being malformed, the registry not being correct, or having Linux as guest:

In practice though, there is a really good change that your default power settings allow Windows to go to sleep after some time of activity. The Windows VM then really sleeps, including services and network adapters. Then VMware ESXi thinks the machine has no VMware tools running:

I have noticed this on ESXi 6.5 and 6.7 with both Windows 7 and Windows 10. It is broader though, as others have seen this in ESXi 5.x as well: [WayBack] VMware Communities : All Content – VMware ESXi 5.

Verifying sleep is enabled

This little trick shows you the various possible sleep states:

C:\>powercfg /availablesleepstates
The following sleep states are available on this system: Standby ( S1 )
The following sleep states are not available on this system:
Standby (S2)
        The system firmware does not support this standby state.
Standby (S3)
        The system firmware does not support this standby state.
Hibernate
        Hibernation has not been enabled.
Hybrid Sleep

Disabling sleep

If you search for “sleep” in the [WayBack] Powercfg command-line options | Microsoft Docs, you have a hard time finding these:

/change or /X

Modifies a setting value in the current power scheme.

Syntax:

/change  setting  value

Arguments:

setting
Specifies one of the following options:

  • monitor-timeout-ac
  • monitor-timeout-dc
  • disk-timeout-ac
  • disk-timeout-dc
  • standby-timeout-ac
  • standby-timeout-dc
  • hibernate-timeout-ac
  • hibernate-timeout-dc
value
Specifies the new value, in minutes.

Examples:

powercfg /change monitor-timeout-ac 5

in order to disable sleep, you hav disable the standby timeouts (suffix -ac means “Plugged in” and -d means “On battery”) by setting their values to 0 (zero) minutes as UAC elevated Administrator:

powercfg /change standby-timeout-ac 0
powercfg /change standby-timeout-dc 0

This is far less than in WayBack – FutureMark forums – windows 7 – how do i disable SLEEP mode via command line ? (via [WayBack] Disable Sleep mode using powercfg – it.megocollector.com), but this is really all you need, as it correctly disables sleeping:

Later I found that [WayBack] windows 7 – How to disable sleep mode via CMD? – Super User also shows this shorter solution.

Note you need to run those on as UAC elevated user, which you can check for using the net session trick in [WayBack] windows – Batch script: how to check for admin rights – Stack Overflow.

–jeroen

Posted in Conference Topics, Conferences, ESXi6.5, ESXi6.7, Event, Power User, Virtualization, VMware, VMware ESXi | Leave a Comment »

Delphi: Passing build variables to batch files; I think the easiest is to use environment variables

Posted by jpluimers on 2021/06/02

A long time ago, I wrote about Delphi prebuild/prelink/postbuild events.

In practice, especially that you cannot inherit build events, then add new ones (), it is convenient to put all you need in a script, for instance a batch file.

Passing parameters to that script, then in my experience, is easiest to do as environment variables.

That way you can do this in a script:

> %temp%\build.txt echo ~dp0=%~dp0
>> %temp%\build.txt echo $(BDS)=%BDS%
>> %temp%\build.txt echo $(INPUTDIR)=%INPUTDIR%
>> %temp%\build.txt echo $(PROJECTDIR)=%PROJECTDIR%
>> %temp%\build.txt echo $(OUTPUTDIR)=%OUTPUTDIR%
>> %temp%\build.txt echo $(Platform)=%Platform%

if "%OUTPUTDIR:~0,2%"==".." set OUTPUTDIR=%INPUTDIR%%OUTPUTDIR%
>> %temp%\build.txt echo $(OUTPUTDIR)=%OUTPUTDIR%

Passing the parameters and calling the script results in this build event contents:

set Platform=$(Platform)
set INPUTDIR=$(INPUTDIR)
set PROJECTDIR=$(PROJECTDIR)
set OUTPUTDIR=$(OUTPUTDIR)
call ..\post-build-event.bat

The IDE then shows this fragment in the project output:

Target PostBuildEvent:
    set Platform=Win32&&set INPUTDIR=D:\Versioned\TestRepostitory\Test Project With Spaces\&&set PROJECTDIR=D:\Versioned\TestRepostitory\Test Project With Spaces&&set OUTPUTDIR=..\EXE Output Directory With Spaces\&&call ..\post-build-event.bat

The above batch file also shows things:

  1. how to handle relative directories in the OUTPUTDIR build parameter: check if the first two characters are .. (trick via [WayBack] Check if Batch variable starts with “…” – Stack Overflow).
  2. spaces are handled fine without any need to double quote the set assignments
  3. build-event lines are concatenated using the && success operator
  4. Parameters INPUTDIR and OUTPUTDIR end with a backslash, but PROJECTDIR does not (Delphi prebuild/prelink/postbuild events explains more about the parameters).

Note:

  • environment variable BDS does not end in a backslash
  • expansion %~dp0 does end in a backslash

With this trick now you can copy BPL files for the right platform:

xcopy /y "%BDS%\Redist\%Platform%\rtl250.bpl" "%OUTPUTDIR%"

Note that the LibSuffix (with value 250 for Delphi 10.2 Tokyo) is not available as environment variable, nor build parameter. The environment variable ProductVersion however (with value 19.0 for Delphi 10.2 Tokyo) is. So technically, you could make a mapping.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »

Delphi: creating copies of installed components to repositories for portability across use cases

Posted by jpluimers on 2021/05/25

Often it is useful to have 3rd party components part of a repository so it is easier to increase portability.

For instance when you want to include or exclude some of them in certain projects by installing/deinstalling them to/from the IDE.

This can be useful for cases where components bite each other, or you want to vary the components in use by version without spinning up new VMs (Delphi registration counts can be a pain for new VMs; you need to be very careful as you can never decrease your registration count).

I usually do this by having 3 batch files:

  1. copy from an installed 3rd party library to a repository in a relative way
  2. register any needed relative files into the IDE
  3. unregister any needed relative files in from the IDE

If successful, I can uninstall the library.

I especially take this approach with 3rd party libraries that stuff to global places (inside the Delphi installation directory, or worse, inside the Windows directories).

That way, I can try to ensure that compilation of running only uses files from the repository, making my options for portability larger.

Examples I did this for are for instance QuickReports and ODAC.

Some bits are tricky to get right, especially loading dependencies.

It helps to understand that for executable files Windows also searches for dependencies in the directory of the executable file.

For libraries, that does not happen. Which means that if a BPL has dependencies, they either have to be explicitly loaded before (for instance by being in the Known Packages registry entries), or on the search PATH.

Delphi has the %BDSCOMMONDIR% directory in the search PATH. It usually points to “%PUBLIC%\Documents\Embarcadero\Studio\%ProductVersion%\Bpl” (where ProductVersion=19.0 for Delphi 10.2 Tokyo).

There might be a away around this using manifests, but this means modifying the BPL files, which is beyond the point of having these copy scripts.

More on those environment variables in a later blog post.

Related:

–jeroen

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Delphi 10.2 Tokyo (Godzilla), Development, Event, Software Development | Leave a Comment »

I wanted to know the loaded DLLs in a process like Process Explorer shows, but from the console: Sysinternals ListDLLs to the rescue

Posted by jpluimers on 2021/05/20

In Windows, historically most people approach investigation GUI first. Having turned 50 a while ago, I am no exception.

My real roots however are on the command-line and scripting: roughly 1980s Apple DOS, CP/M, SunOS (yay sh Bourne shell!), MS-DOS, 4DOS, and VAX/VMS (yay DCL shell!), from the 1990s on, some Solaris, a little bit of AIX, HP-UX and quite a bit of Linux, MacOS (né OS/XMac OS),  and some BSD descendants derivatives (SunOS, AIX and MacOS are based on the Berkeley Software Distribution), and this century a more growing amount of PowerShell).

So I was glad to find out the makers of Process Explorer also made [WayBack] ListDLLs – Windows Sysinternals | Microsoft Docs (via windows get dlls loaded in process – Google Search)

List all the DLLs that are currently loaded, including where they are loaded and their version numbers.

ListDLLs is a utility that reports the DLLs loaded into processes. You can use it to list all DLLs loaded into all processes, into a specific process, or to list the processes that have a particular DLL loaded. ListDLLs can also display full version information for DLLs, including their digital signature, and can be used to scan processes for unsigned DLLs.

Usage

listdlls [-r] [-v | -u] [processname|pid]
listdlls [-r] [-v] [-d dllname]

Parameter Description
processname Dump DLLs loaded by process (partial name accepted).
pid Dump DLLs associated with the specified process id.
dllname Show only processes that have loaded the specified DLL.
-r Flag DLLs that relocated because they are not loaded at their base address.
-u Only list unsigned DLLs.
-v Show DLL version information.

Download: [WayBack] ListDlls.zip.

Now it is much easier to generate a draft deploy list of DLLs (and for Delphi: BPLs) based on a process running on a development machine.

Example output (the -r flags relocation warnings; the first part is the [WayBack] shim that Chocolatey created around the second which is from SysInternals):

Read the rest of this entry »

Posted in Conference Topics, Conferences, Delphi, Development, Event, History, Software Development, Windows Development | Leave a Comment »

Much Turbo Pascal history (via What is a Delphi DCU file? – Stack Overflow)

Posted by jpluimers on 2021/05/19

Editing [WayBack] What is a Delphi DCU file? – Stack Overflow for more historic correctness and adding links prompted me to archive some older material and search for some more, basically because while historically very relevant, link rot makes a lot of that stuff harder and harder to find.

The legendary full page colour advert published in the 12th 1983 issue of Byte Magazine on page 456 is at the bottom of this post (Many BYTE magaine issues have been archived at https://archive.org/details/byte-magazine).

The smaller version below is from WayBack: Sip from the Firehose : November 2008 marks the 25th anniversary of Turbo Pascal v1.0! (this article is not available on the Embarcadero or Idera site any more).

I also included more adverts in reverse chronological order at the end:

The last two via [WayBack] saundby.com: Software for the Ampro Little Board.

--jeroen

Read the rest of this entry »

Posted in Conference Topics, Conferences, CP/M, Delphi, Development, Event, History, MS-DOS, Pascal, Power User, Software Development, Turbo Pascal, UCSD Pascal, Z80 | Leave a Comment »

Delphi: EInvalidOp exception, might just mean you have a use-after free scenario, or an out-of-bounds value

Posted by jpluimers on 2021/05/13

Quite some time ago, I was researching spurious exceptions in a Delphi application, then finally replicated them in a unit test suite.

One of them was occurring almost all of the time: EInvalidOp.

It is one of the floating point exceptions (incidentally exampled at [WayBack] Exceptions: Declaring Exception Types) all inheriting from the [WayBack] EMathError Class:

EMathError is the base class for floating-point math exception classes. EMathError itself is never raised.

The following exceptions descend from EMathError:

Meaning
Parameter out of range
Processor encountered an undefined instruction
Floating-point operation produced result too large to store
Floating-point operation produced result with no precision
Attempt to divide by zero

Run-time exception information is saved in fields provided by [WayBack] EExternal.

Use-after-free

In my first case (which I described in delphi – Invalid floating point operation calling Trunc()), not all input scenarios had been tested in a certain scenario. In a production environment, one of the inputs was really high.

In a later case, the actual cause was not a floating point problem at all, but a use-after-free scenario that overwrite a floating point value with something not so compatible also causing a simple Trunc statement to fail in the same way.

In that case, the production data could never reach the big numbers that failed, so no new tests were needed.

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | Leave a Comment »