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,854 other subscribers

Archive for 2021

Hoe is het nu met Zivver?

Posted by jpluimers on 2021/03/05

Twee jaar geleden had ik een interessante Twitter berichtenwisseling met Zivver.

Hun product was voor geadresseerden verre van gebruikersvriendelijk, en ook had ik vraagtekens bij de privacy.

Dit is een reminder om eens te kijken hoe het hen vergaan is.

Thread:

Gerelateerd:

–jeroen

Posted in GDPR/DS-GVO/AVG, Power User, Privacy | Leave a Comment »

Office 2013 Proofing tools downloads

Posted by jpluimers on 2021/03/05

For my link archive:

Via:

Posted in Office, Office 2013, Power User, Word | Leave a Comment »

Memories box (:

Posted by jpluimers on 2021/03/05

The earliest picture of this memories I could find was on [WayBack] Head nalja tõsistele finants-geek’idele :-) – Vaba teema – Foorum – LHV finantsportaal

Maybe one with a perspex front is easier (less dust, easier to keep clean), but I like the idea very much.

Via: [WayBack] Shawn Wildermuth 💻☕🎸🎥🎮 on Twitter: “I need this:… “

–jeroen

Posted in Fun, Power User | Leave a Comment »

reg query and batch file for loop tricks that refreshes the cmd environment from the registry settings: choco/RefreshEnv.cmd at master · chocolatey/choco · GitHub

Posted by jpluimers on 2021/03/04

I bumped into a very interesting [WayBack] choco/RefreshEnv.cmd at master · chocolatey/choco · GitHub.

It allows you to refresh your cmd environment from new settings that were only applied to the registry using the SET command.

Note there is a PowerShell counterpart too: [WayBack] choco/Update-SessionEnvironment.ps1 at master · chocolatey/choco · GitHub

There are many cool tricks in it, most of which you can see in the [WayBack] new commit history, and a few you can find back in the [WayBack] old commit history of the previous repository (I have no idea why those histories have never been merged).

Intermediate batch files

The basic structure is to first create some intermediate batch files, then delete them afterwards:

  • "%TEMP%\_envget.tmp"
    • is used in :GetRegEnv to get all environment variables for the MACHINE or USER level, then loop through them and call :SetFromReg during each iteration (except for the Path environment variable which is skipped).
  • "%TEMP%\_envset.tmp"
    • is used in :SetFromReg to emit one line of SET code to "%TEMP%\_env.cmd".
  • "%TEMP%\_env.cmd"
    • Contains the SET commands for the new environment variable values.

All the above methods use quoting to ensure that environment variables having names or values containing spaces are handled correctly.

Echo without newline

I like the echo | set /p trick to echo a string without a newline allows it to start as this:

C:\>RefreshEnv
Refreshing environment variables from registry for cmd.exe. Please wait...

then finish like this by appending another string to it:

C:\>RefreshEnv
Refreshing environment variables from registry for cmd.exe. Please wait...Finished..

It is explained in the old history at [WayBack] (GH-153)(GH-134) Update PATH on cmd.exe · chocolatey/chocolatey@a09e158 · GitHub.

There is an even more interesting example of this trick in [WayBack] windows – What does /p mean in set /p? – Stack Overflow:

<nul set /p=This will not generate a new line

Spaces, what spaces

One hard thing in scripting is taking into account that path names can contain spaces. This means you need to carefully quote path names, but not overdo the quotes, otherwise the quoting works against you.

Two commits from the commit history show there were two weak spots that had to be changed in [WayBack] (GH-1227) Fix: RefreshEnv doesn’t set path w/spaces · chocolatey/choco@fdfcd06 · GitHub.

The environment has a MACHINE and USER part

Environment variables can come from two places in the registry:

  • HKLM\System\CurrentControlSet\Control\Session Manager\Environment
  • HKCU\Environment

Normally, the second overrides the first.

This means they are grabbed from the registry MACHINE and USER order, then applied to the cmd environment.

Special case PATH

The PATH environment variable is special for two reasons:

  1. In the registry it is called Path, but in the environment it is usually called PATH (this is true for both the MACHINE and USER parts of the registry). New values are applied with the Path environment variable name, so after executing RefreshEnv once, they are called Path in the cmd.exe environment too.
  2. PATH is a combination from two PATH entries in the registry in the MACHINE and USER level, so it needs to be combined as you can see in [WayBack] choco/RefreshEnv.cmd at master · chocolatey/choco · GitHub.:
    :: Caution: do not insert space-chars before >> redirection sign
    echo/set "Path=%%Path_HKLM%%;%%Path_HKCU%%" >> "%TEMP%\_env.cmd"

I am not sure why there is a space before the >>, given there is a comment above it there should not be one.

The SET command however, puts the MACHINE PATH in front of the USER PATH.

Special case USERNAME, and collateral PROCESSOR_ARCHITECTURE

The USERNAME environment variable special too. In the registry, it is only in the MACHINE part, but with a value SYSTEM.

In cmd.exe, it is actually filled with the current username, so it should not be overwritten with the one in the MACHINE part.

Currently this is resolved by storing a copy of the old value of USERNAME and PROCESSOR_ARCHITECTURE in [WayBack] (GH-902) Fix: User changed to SYSTEM during env update · chocolatey/choco@cb6b92c · GitHub.

I am not sure why PROCESSOR_ARCHITECTURE is also stores.

In any case, this means that setting a USERNAME or PROCESSOR_ARCHITECTURE in the USER part of the registry, will not be reflected by RefreshEnv.

I am not sure yet when that can cause problems, so this is a reminder to myself that if ever it does, then this logic needs to be changed.

–jeroen

Posted in Batch-Files, Development, Scripting, Software Development | Leave a Comment »

Short Delphi tip: ensuring RTTI for classes is included

Posted by jpluimers on 2021/03/04

When using RTTI in Delphi, you really want the RTTI to be available.

The compiler includes RTTI for classes, as soon as it found that a class is touched by code that will be executed.

So in order to include RTTI for classes into the executable, you have to ensure you touch the class.

Basically there are two tricks for that.

  1. A small one step process which incurs a tiny bit of string overhead:
    class function TObject.ClassName: string;
    begin
      Result := UTF8ToString(_PShortStr(PPointer(PByte(Self) + vmtClassName)^)^);
    end;
    • Touch the [WayBack] ClassName class function for each class, for instance in an initialization section or registration method, like this:
      TMyClass.ClassName;
      TMyOtherClass.ClassName;
  2. A small two step process
    1. Create a method like this: procedure EnsureRttiIsAvailable(const Classes: array of TClass); begin end;
    2. Pass the classes to it like this:
      EnsureRttiIsAvailable([TMyClass, TMyOtherClass]);

I like the second solution more, as it clearly states the intent.

The first trick is calling a function without using the result. This is a Pascal construct that looks odd, but is perfectly valid to use: basically you discard the result.

–jeroen

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

Delphi: combining intrinsic functions and inline to have no-code checks on concrete generic instantiation

Posted by jpluimers on 2021/03/04

The title might sound like a lot of gibberish, but the mechanism it describes helps solving a problem when using generics: lack of generic constraints in the compiler.

For instance, you cannot constrain on enumeration types (C# could not do this either: you could not do T GetEnumFromString<T>(string valueString, T defaultValue) where T : Enum, but [WayBack] since C# 7.3, you can do ... where T : Enum) unless you [WayBack] did some real hackery.

For Delphi, you still cannot do the constraint, but with some hackery, you can avoid code generation. Spring4d uses this in [WayBack] Spring.pas, from which I copied these fragments:

class function TType.Kind<T>: TTypeKind;
{$IFDEF DELPHIXE7_UP}
begin
  Result := System.GetTypeKind(T);
{$ELSE}
var
  typeInfo: PTypeInfo;
begin
  typeInfo := System.TypeInfo(T);
  if typeInfo = nil then
    Exit(tkUnknown);
  Result := typeInfo.Kind;
{$ENDIF}
end;

class procedure Guard.CheckTypeKind<T>(expectedTypeKind: TTypeKind;
  const argumentName: string);
begin
  if TType.Kind<T> <> expectedTypeKind then
    RaiseArgumentException(TType.Kind<T>, argumentName);
end;

class function TEnum.IsValid<T>(const value: Integer): Boolean;
var
  data: PTypeData;
begin
  Guard.CheckTypeKind<T>(tkEnumeration, 'T');
  data := GetTypeData(TypeInfo(T));
  Result := (value >= data.MinValue) and (value <= data.MaxValue);
end;

When <T> is an enumeration type, any code for that call is eliminated by the compiler.

Related

Concrete versus generic type:

–jeroen

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

Common UX ant-pattern: “you have Tea and No Tea”

Posted by jpluimers on 2021/03/03

I see this pattern in a lot of user interfaces, especially on web-sites: “you have Tea and No Tea”.

For instance the example from the web site on the right: it indicates in Dutch you are getting a postal package. In the body text it says “because we send it as a letter, you do not get a tracking code” followed by a headed section containing a link to an invalid tracking code.

There was only one historic case where the condition “you have Tea and No Tea” opened doors.

Nowadays you should just put a user story on your front-end team back-log that prevents displaying a tracking code when there is none.

Maybe file an issue for the back-end team as well, to distinguish the cases where you can or cannot track shipments.

If you fix it, then an important to remember that often multiple front-ends share the same code.

In the case of the screen shot on the right, the email system showed the same issue; a strong indication either part of the code, or the design steps have been shared.

For such cases, it helps tracking back where the root of the shared design or code came started, then ensure everything stemming from that root is re-checked to ensure altered copies are inspected for the need of modification.

Background

[WayBack] Thread by @jpluimers: “Er gaat iets mis met @KPNwebcare PostNL tracking codes voor prepaid SIM kaarten vanaf mijnbestelling.kpn.com : de “PostNL Track & Trace […]”

Er gaat iets mis met @KPNwebcare PostNL tracking codes voor prepaid SIM kaarten vanaf mijnbestelling.kpn.com : de “PostNL Track & Trace code” link mist de 3S en ziet er nu uit als jouw.postnl.nl/#!/track-en-tr… waarbij op * 20 cijfers staan zonder 3S erin.

Hoe krijg ik de goede code?

Ah, een typisch geval van “you have Tea and No Tea” waarbij “Tea” de aandacht trekt, maar “No Tea” niet.

Mooie user story voor een backlog item van jullie front-end scrum teams (;

Applaus als jullie trouwens laten zien deze klassieker te kennen (;

and [WayBack] Thread by @jpluimers: “@KPNwebcare Doe ik. Zowel site als email hebben hetzelfde probleem. @KPNwebcare Daar zitten deze twee zinnen in: “Handig om te weten: omdat […]”

Doe ik. Zowel site als email hebben hetzelfde probleem.
mentions Daar zitten deze twee zinnen in:

“Handig om te weten: omdat uw bestelling via post wordt verstuurd, is het niet mogelijk om deze via een Track & Trace code te volgen”

en

“Track & Trace code
Dit is uw persoonlijke PostNL Track & Trace code”

Met daarin dezelfde foutieve link.

–jeroen

Read the rest of this entry »

Posted in Development, Software Development, Usability, User Experience (ux) | Leave a Comment »

Delphi: quickly failing in use-after free scenarios

Posted by jpluimers on 2021/03/03

Two tricks that can help in use-after-free scenarios.

Call ScanMemoryPoolForCorruptions often

One of the scenarios of use after free, is that memory blocks get corrupted.

FastMM4 normall checks this at process end using the CheckBlocksOnShutdown method (in FastMM4.pas when writing this private at line 11156), but you can also do this process manually using the ScanMemoryPoolForCorruptions method (also in FastMM4.pas, but public at line L1356).

You can automate this process by setting the FullDebugModeScanMemoryPoolBeforeEveryOperation flag to True while in FullDebugMode as you see in the quoted code blocks below.

Note that calling ScanMemoryPoolForCorruptions between allocations might reveal wild pointer dereferences between allocations.

  - Added a global variable "FullDebugModeScanMemoryPoolBeforeEveryOperation".
    When this variable is set to true and FullDebugMode is enabled, then the
    entire memory pool is checked for consistency before every GetMem, FreeMem
    and ReallocMem operation. An "Out of Memory" error is raised if a
    corruption is found (and this variable is set to false to prevent recursive
    errors). This obviously incurs a massive performance hit, so enable it only
    when hunting for elusive memory corruption bugs. (Thanks to Marcus Mönnig.)

  {If this variable is set to true and FullDebugMode is enabled, then the
   entire memory pool is checked for consistency before every memory
   operation. Note that this incurs a massive performance hit on top of
   the already significant FullDebugMode overhead, so enable this option
   only when absolutely necessary.}
  FullDebugModeScanMemoryPoolBeforeEveryOperation: Boolean = False;

Call any virtual method on an instance reference

A quick way to test use-after free scenarios is to call a virtual method on an instance.

Virtual methods mean that the Virtual Method Table needs to be used as a starting point, so any nil pointer will get dereferenced.

Two simple methods that you can call, which have no side effects, except for referencing memory, and are virtual on [WayBack] TObject are [WayBack] GetHashCode and [WayBack] ToString. Both methods got added in Delphi 2009, and now support 64-bit and 32-bit compilers are below.

If you use use these in addition to FastMM4 clearing memory, and FastMM4 redirecting virtual methods of freed objects, you have a good chance of catching use-after free.

Without FastMM, they are also of good help, especially when the freed memory has since then been overwritten by new usage. FastMM4 is a lot more strict about this, so definitely recommended.

Calling these two methods help you to quickly fail with an EAccessViolation [WayBack] in use-after-free scenarios.

More on the virtual method table is for instance in [WayBack] Hallvard’s Blog: Method calls compiler implementation.

Read the rest of this entry »

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

JSON or binary stream? Delphi 2010: How to save a whole record to a file? – Stack Overflow

Posted by jpluimers on 2021/03/03

A while back I proposed using JSON in order to [WayBack] Delphi 2010: How to save a whole record to a file? – Stack Overflow.

There is also a native solution using streaming (which by now has moved to [WayBack] GitHub – KrystianBigaj/kblib: Automatically exported from code.google.com/p/kblib with main source file [WayBack] kblib/uKBDynamic.pas), but be aware that unlike JSON:

  • Streams are not fully compatible between Delphi Unicode and Delphi non-Unicode (they are if you limit yourself to AnsiString)
  • Streams are not compatible between x64 and x86 unless you use kdoCPUArchCompatibility and provide additional compatibility (read comments on kdoCPUArchCompatibility)

The main file from my proposed solution has since then move

Which reminds me I still need to fix quite a few links, as per Anyone who knows about http://sourceforge.net/p/radstudiodemos/code/HEAD/tree/branches/RADStudio_Rio ?

–jeroen

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

Reminder of Windows 10 update “What’s New” location

Posted by jpluimers on 2021/03/02

If you forgot what Microsoft has added, look for a file named like this:

C:\Program Files\WindowsApps\Microsoft.Getstarted_7.3.20251.0_x64__8wekyb3d8bbwe\WhatsNew.Store.exe

Disregard any warnings you find through the above link: it is a legit file installed during Windows 10 update.

–jeroen

Posted in Power User, Windows, Windows 10 | Leave a Comment »