The Wiert Corner – irregular stream of stuff

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

  • My badges

  • Twitter Updates

  • Pages

  • All categories

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

    Join 1,839 other subscribers

Jira “Preformatted” is not “Preformatted”

Posted by jpluimers on 2020/12/25

Found out that Jira has its own markdown for issues and comments.

I knew the editor for it has a Style drop down with a “Preformatted” entry.

Initially, pasted text looks preformatted, but after saving the issue or comment, often all or part of that text did either:

  • did not display as preformatted
  • had curly braces around them

A co-worker indicated the plus sign on the right can insert blocks (I thought that while it was next to inserting emoticons, it was for inserting unicode symbols like plus).

Alas, no: it is for adding things that are not symbols at all, and too has a “Preformatted” entry.

For sake of consistency, both “Preformatted” entries produce different markup.

The “Style” entry of “Preformatted” basically surrounds all lines with curly braces, then upon saving tries to do some interpretation and removes parts.

The “Plus” entry of “Preformatted” surrounds a block of lines with {noformat} entries at start of end.

Then there is the “Code” entry under “Plus”. It insert a code block, does not allow you to select the language, but assumes everyone loves programming in Java, as now the surrounding entries are {code:java} at the start and {code} at the end. The default block is this one in “Visual” mode:

{code:java}
// code placeholder
{code}

and this one in “Text” mode:

Read the rest of this entry »

Posted in Development, Issue/Bug tracking, JIRA, Power User, Software Development | Leave a Comment »

Electronics-Salon DIN Rail Mount +/-20Amp AC/DC Current Sensor Module, based on ACS712: Amazon.com: Industrial & Scientific

Posted by jpluimers on 2020/12/24

For my link archive (this DIN rail device allow sensing current used by a circuit; models for 5A/20A/30A).

Thanks Matthijs ter Woord for pointing me to this.

Schematics show it uses an LM317 linear voltage regulator (to get 5V out of a 8V-35V range) next to the ACS712 current sensor (based on the [WayBack] Hall effect) available in 5A, 20A and 30A varieties.

Documentation:

Schematics:

 

Read the rest of this entry »

Posted in Development, Hardware, Hardware Development, Hardware Interfacing | Leave a Comment »

Essential versus Accidental Complexity: 2 minute Kevlin Henney video and some links

Posted by jpluimers on 2020/12/24

The topic is as old as the 1986 “No Silver Bullet” book, still relevant, but few people are consciously aware of the difference of these fundamental ideas:

Essential versus Accidental Complexity

TL;DR:

  • Essential complexity is the problem you try to solve
  • Accidental complexity is the problems you have created while solving

The first is what it is all about (it is in your problem domain, and not reducible); the second is what you want to minimise, like technical debt, size effects of quick fixes, bad tool/framework/language choices, long feedback loops.

2 minute video:

Related:

Via:

–jeroen

Read the rest of this entry »

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

Is this code safe? function Some(const Str : AnsiString); var arr : TBytes …

Posted by jpluimers on 2020/12/24

[WayBack] Is this code safe? function Some(const Str : AnsiString); var arr : TBytes absolute Str; begin fSomeMethodWithTBytesParam(arr); <- arr is properly c… – Jacek Laskowski – Google+

Such a seemingly simple question:

Is this code safe?

procedure Some(const Str : AnsiString); 
var arr : TBytes absolute Str; 
begin
  fSomeMethodWithTBytesParam(arr); // <- arr is properly casted to string bytes? 
end;

Such a wealth of information in the comments:

  • No it is not, except for the nil-pointer case
  • The compiler has for instance an implicit length prefix
  • In 32-bit mode, the Length prefix of strings and dynamic arrays are both 32-bits
  • In 64-bit mode, the Length prefix of strings is 32-bits, but the one for dynamic arrays is 64-bits
  • use BytesOf to transform from characters to bytes
  • do not store binary data into strings of single-byte character sets

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »

PlasticSCM memories

Posted by jpluimers on 2020/12/23

Spending most of your career as an independent contractor, you bump into a lot of toolchains.

Part of those toolchains usually involved (and by now surely should involve) version control for both development and infrastructure configuration management.

I remember PlasticSCM quite well.

The really good part is the branch overview (called Branch Explorer) in the PlasticSCM UI, as it is:

They also have frequent updates, which however are hard to discover because there is no built-in update mechanism that notifies you of them.

Those updates are badly needed, because I kept bumping into bugs. Which is odd, because I bumped into far less issues when using UI layers for SVN, TFS, Mercurial and git (SourceTree being a major exception, but they seem to have recovered from a long period of bad versions a few years back).

So here are some of my gripes, that might have been fixed by now.

Read the rest of this entry »

Posted in Delphi, Development, PlasticSCM, Software Development, Source Code Management, Versioning | Leave a Comment »

Some links on MS UIA: UI Automation

Posted by jpluimers on 2020/12/23

For my link archive:

A Delphi implementation:

–jeroen

Posted in accessibility (a11y), Development, Software Development | Leave a Comment »

How to debug Delphi JSON export stack-overflows: watch the fields and their circular references

Posted by jpluimers on 2020/12/23

Unlike Delphi RTL XML support which is property based, the JSON support is field based.

By default, JSON uses all fields (no matter their protection level, so anything from strict private to published  is taken into account).

When there are cycles, they are not detected: it will just stack-overflow with a high set of entries like this:

REST.JsonReflect.{REST.JsonReflect}TTypeMarshaller.MarshalSimpleField($788BFB40,$78AB0150)
REST.JsonReflect.{REST.JsonReflect}TTypeMarshaller.MarshalData($78AB0150)
REST.JsonReflect.{REST.JsonReflect}TTypeMarshaller.MarshalValue((($A9B7E8, Pointer($AFE168) as IValueData, 80, 336, 2024472912, $78AB0150, TClass($78AB0150), 80, 336, 2024472912, 2,77471682335019e+34, 1,00022251675539e-314, 0,00000000737961e-4933, 2024472912, 202447,2912, 2024472912, 2024472912, ($78AB0150, nil), $78AB0150)),???)
REST.JsonReflect.{REST.JsonReflect}TTypeMarshaller.MarshalSimpleField($78A921D0,$78AA69C0)
REST.JsonReflect.{REST.JsonReflect}TTypeMarshaller.MarshalData($78AA69C0)
REST.JsonReflect.{REST.JsonReflect}TTypeMarshaller.Marshal(???)

The easiest way to debug this is to:

  1. Set breakpoints in procedure TTypeMarshaller<TSerial>.MarshalData(Data: TObject);
    1. First breakpoint on the for rttiField loop
      • Watch or log these values (the first two usually are the same, the last two too):
        1. ComposeTypeName(Data) which gives you the fully qualified name (including unit and class) of the type exposing the fields
        2. Data.ClassName as a sanity check
        3. rttiType.Name which should be the same as Data.ClassName
    2. Second breakpoint inside the for rttiField loop on the if not ShouldMarshalstatement
      • Watch or log these values:
        1. rttiType.Name inside the loop, it changes value to match rttiField.Name, because of a debugger bug not showing it as E2171 Variable 'rttiType' inaccessible here due to optimization.
        2. rttiField.Name the actual field name

Tricks to circumvent circular references:

  • remember that fields with a reference to function value are not marshaled, so they are an excellent way of shoehorning in a dependency in (the reference value will be a capture which includes the instance data of the function to be called)
  • applying a [JsonMarshalled(False)] attribute (be sure to use unit REST.Json.Types!) only works when used inside non-generic types:
    • a class like TMySoapHeaderValue<T: IInterface> = class will not expose these attributes
    • a class like TMySoapHeaderValue = class will expose these attributes

You can check the JsonMarshalled problem by setting a breakpoint inside function LazyLoadAttributes(var P: PByte): TFunc<TArray<TCustomAttribute>>; on the line Exit(nil); and watch the value for Handle^.

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

Some odd Windows Messages for my research list (Windows 10 with a very basic Delphi application)

Posted by jpluimers on 2020/12/22

The bold messages below inside the main message loop are on my research list because:

  • they seem to be undocumented in WinUser.h and other header files
  • they are sent to Window handles that have no corresponding VCL TWinControl bound to them
  • they are WM_TIMER messages sending to a null hwnd, without the Delphi code registering a window-less timer (note the lParam indicates they have different call back procedures attached to them)

Being inside the message loop, they are either posted or created by Windows.

The hexadecimal value for WM_TIMER is documented: [Archive.is] 0x0113 site:https://docs.microsoft.com/en-us/windows/desktop/winmsg – Google Search.

Neither of the below messages are documented in either of the Undocumented Windows books (yes, there are two; the first – though rare to get – was a slightly earlier published one-person effort; the second was a tiny bit later three-person effort, but much thicker and included a diskette with tools; both books complement each other well; I am listed in both):

Messages I am looking for:

Yes, I know that Windows Messages are usually noted as 4 hexadecimal digits, but since they are UINT, the logging framework logs them as 32-bit hexadecimal values as this was a 32-bit application, see these WM_* constants and message ranges:

  • 0x0400: [WayBack] WM_USER – Windows applications | Microsoft Docs
  • 0x8000: [WayBack] WM_APP – Windows applications | Microsoft Docs

    The WM_APP constant is used to distinguish between message values that are reserved for use by the system and values that can be used by an application to send messages within a private window class. The following are the ranges of message numbers available.

    Start End Meaning Note
    0 WM_USER–1 Messages reserved for use by the system.
    WM_USER 0x7FFF Integer messages for use by private window classes. Depends on the one that called RegisterClass, see below.
    WM_APP 0xBFFF Messages available for use by applications. Depends on the one that called CreateWindow, see below.
    0xC000 0xFFFF String messages for use by applications.
    0x10000 0xFFFFFFFF Reserved by the system.

Note that [WayBack] Which message numbers belong to whom? – The Old New Thing explains more about CreateWindow and RegisterClass, which are important for the above subranges.

Similarly, the sharing of the ID space for Windows Messages, Atom Names and Clipboard Formats:

It might be that two of the messages are related to an undocumented UserAdapterWindowClass: [WayBack] Windows Creators Update Crashes old C++ Apps – Stack Overflow.

On message handling in general:

Related (as my WM_TIMER knowledge was rusty when scheduling this blog post):

Read the rest of this entry »

Posted in Development, Software Development, The Old New Thing, Windows Development | Leave a Comment »

winapi – What format is the time member of a MSG structure? – Stack Overflow

Posted by jpluimers on 2020/12/22

Found it. GetMessageTime defines it as the number of milliseconds since the system was started.

Source: [WayBack] winapi – What format is the time member of a MSG structure? – Stack Overflow.

It is not documented in the MSG/tagMSG documentation: [WayBack] tagMSG | Microsoft Docs Contains message information from a thread’s message queue.

Luckily, The Old New Thing does: [WayBack] What clock do MSG.time and GetMessageTime use? – The Old New Thing

The unit is documented in [WayBack] GetMessageTime function | Microsoft Docs: Retrieves the message time for the last message retrieved by the GetMessage function.

–jeroen

Posted in Development, Software Development, The Old New Thing, Windows Development | Leave a Comment »

If you control both caller and callee: do not “override” functions by introducing a function with the same name

Posted by jpluimers on 2020/12/22

Every now and then I see people “overriding” a function by introducing a function with the same name.

Often this raises a lot of confusion, because the override will only work if you have the unit of the override closer in your user scope.

Example:

Unit AdoOverrideUnit;

interface

function VarTypeToDataType(VarType: Integer): TFieldType;

implementation

uses
  Data.DB;

function VarTypeToDataType(VarType: Integer): TFieldType;
begin
  Result := Data.DB.VarTypeToDataType(VarType);
  // override Result for some ADO specific data management layer case.
  // ...
end;

end.

In this case it is much better to call the override AdoVarTypeToDataType instead of VarTypeToDataType.

Otherwise, when AdoOverrideUnit is not closer in scope than Data.DB, the wrong method will be called which is hard to track down.

–jeroen

Posted in Delphi, Development, Software Development | Leave a Comment »