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 the ‘Software Development’ Category

delphi – What are the list of all possible values for DVCLAL? – Stack Overflow

Posted by jpluimers on 2020/11/17

From a while ago, from notes even longer ago – around 1994 on DVCLAL the Delphi VCL Access License code which is actually a checking logic for determining the SKU (stock keeping unit) or Delphi license: [WayBack] delphi – What are the list of all possible values for DVCLAL? – Stack Overflow

There is no official documentation on this, so here is something from my notes of 15+ years ago:

The DVCLAL is there to check which SKU of Delphi you are using and it varies per SKU.

There are only checks for the Professional (RPR) and Client/Server (RCS) SKUs:

procedure RCS;

procedure RPR;

If they fail, they call this method:

procedure ALV;
begin
  raise Exception.CreateRes(@SNL);
end;

where

resourcestring
  SNL = 'Application is not licensed to use this feature';

Depending on the feature matrix and Delphi version, various components call RPR and RCS in their Create constructors to guarantee a minimum SKU.

Underneath, these RPR and RCS functions call the function  GDAL . Their names are historic and got documented around Delphi 2007:

  • [WayBack] GDAL (Get Delphi Access License)
  • [WayBack] RPR will Restrict to PRofessional license and higher
  • [WayBack] RCS will Restrict to Client/Service license and higher

Historically you had these levels of Delphi editions that could be distinguished this way:

  1. Personal
  2. Professional
  3. Client/Server (or Enterprise)

This excludes Starter and Community (which are “just” Personal), Turbo (which was “just” Professional), Architect and Ultimate, which are “just” Client/Server with extra tools.

A few years ago, another answer got added to that question explaining more details:

I am just adding another answer to this question, for all the people who search the for actual DVCLAL (Delphi Visual Component Library Access License) values, as well as some other information for all people who are curious how stuff works.

1) Like Jeroen Wiert Pluimers said, if you want to check for “Professional or higher” or “Enterprise only” inside your Delphi application/library/package/component, you can use RPR (Require Professional) or RCS (“Require Client/Server”; Client/Server was the name for the Enterprise edition in early Delphi versions) respectively. If the requirement is not met, ALV (Access License Violation) will be called which will raise an Exception with the message defined in SysConst.SNL (S Not Licensed). In English:

Application is not licensed to use this feature

2) In case you want to check for one specific edition, you can use the output of the function GDAL (Get Delphi Access License), which is one of the following (AL1s array):

AL1s[0] = $FFFFFFF0; // Standard/Personal edition DVCLAL value
AL1s[1] = $FFFFEBF0; // Professional edition DVCLAL value
AL1s[2] = $00000000; // Enterprise/ClientServer edition DVCLAL value
AL1s[3] = $FFFFFFFF; // DVCLAL resource not existing

if the DVCLAL resource has an invalid value, GDAL will call ALVwhich will raise an Exception with message SysConst.SNL.

3) In case you want to check the DVCLAL value of a foreign EXE/DLL file (e.g. if you want to write a Resource Editor, decompiler etc), then you’ll have to query the DVCLAL resource directly.

There are only three official values:

Standard:      23 78 5D 23 B6 A5 F3 19 43 F3 40 02 26 D1 11 C7
Professional:  A2 8C DF 98 7B 3C 3A 79 26 71 3F 09 0F 2A 25 17
Enterprise:    26 3D 4F 38 C2 82 37 B8 F3 24 42 03 17 9B 3A 83

4) Just for fun: If you solve the formula 0 = (ROR(a,15) xor a) xor (ROR(b,10) xor b) xor (ROR(c,5) xor c) xor (AL1 xor AL2) you can define any DVCLAL value (tuple a, b, c, d) you want! (AL1 and AL2 are the values in the AL1s and AL2s arrays which describe the desired Delphi edition; ROR is rotate right through carry)

For example, here are alternative DVCLALs which work too:

Standard:      00 00 00 00 00 00 00 00 9B 70 0C 66 6B 8F F3 99
Professional:  00 00 00 00 00 00 00 00 9A DB 73 0F 6A 30 8C F0
Enterprise:    00 00 00 00 00 00 00 00 D8 B2 48 11 D8 B2 48 11

To validate a DVCLAL, you calculate

AL1 := DVCLAL[0] xor DVCLAL[1] xor DVCLAL[2] xor DVCLAL[3];
AL2 := ROR(DVCLAL[0],15) xor ROR(DVCLAL[1],10) xor ROR(DVCLAL[2],5) xor DVCLAL[3];

and look up AL1 and AL2 in the array AL1s and AL2s,

This way you can disguise the edition you have used a little.

5) In the meantime, an official documentation, at least for the functions GDALRPR and RCS, has been published.

6) Of course, everything works for C++ Builder, too.

In the mean time, new posts explaining bits of DVCLAL related resources (like PACKAGEINFO and CHARTABLE) and the TPF0 form/datamodule resource have appeared, of which this is a selection:

jeroen

miscprogs.zip

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

powershell – Format-Table forgets some properties, but Format-List shows them all. Why? – Stack Overflow

Posted by jpluimers on 2020/11/12

Reminder to self: finish the script that initiated this 2013 question (yes ages ago!) [WayBack] powershell – Format-Table forgets some properties, but Format-List shows them all. Why? – Stack Overflow.

The question was based on code I was really happy I saved in the WayBack machine: WayBack: how-to: Print/List installed programs/applications sorted by date | Tech Off | Forums | Channel 9

So here the question and the answer.

Read the rest of this entry »

Posted in .NET, CommandLine, Development, PowerShell, PowerShell, Scripting, Software Development | Leave a Comment »

Tracking down Delphi “abstract error” occassions.

Posted by jpluimers on 2020/11/12

A few tips.

  1. Set breakpoints in these units:
    • System.pas:
      procedure _AbstractError;
      begin
        if Assigned(AbstractErrorProc) then
          AbstractErrorProc;
        RunErrorAt(210, ReturnAddress);
      end;
    • System.SysUtils.pas:
      procedure AbstractErrorHandler;
      begin
        raise EAbstractError.CreateRes(@SAbstractError);
      end;
  2. add a watch for ClassName that has “Allow side effects and function calls” enabled
  3. run your code until it breaks or stops (usually in the first method above)
  4. double click on each entry in the “Call Stack” pane, and for each entry:
    • set a break point on the call to the method above it in the stack trace
    • note that sometimes this is on the line you arrived, but sometimes one more more lines higher in your code
    • the cause is that the stack trace will show you where your code will RETURN to, not the place it was CALLED FROM.
  5. abort your program
  6. run your program again
  7. on each hit breakpoint, watch the value of ClassName:
    • if it becomes [WayBackE2003: Undeclared identifier: 'ClassName', then:
      • observe the method directives
      • if it includes static, but it is actually inside a class, then remove the static

Sometimes you cannot perform the last step: class property definitions have to be backed by static class methods.

This usually means you have a bad design anyway: you depend on global/singleton kind of behaviour that is almost impossible to properly test.

A better approach is to have regular object instances for that, then use constructor dependency injection (maybe combined with factory or dependency injection container) to setup the structures of dependencies.

TODO

Create a conference summary on the use of class versus instance methods, and static/regular.

Base materials:

–jeroen

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

How to quickly add hours/minutes/second to date and time in Excel?

Posted by jpluimers on 2020/11/11

Excel date times are almost identical to OLE/COM automation date times (that used in many Windows applications).

Which means that dates are 1 unit apart, and:

  • Weeks = 7
  • Days = 1
  • Hours = 1/24
  • Minutes = 1/(24*60) or 1/1440
  • Seconds = 1/(24*60*60) or 1/86400

That way you can easily add one hour to a date/time value by adding 1/24.

Source: How to quickly add hours/minutes/second to date and time in Excel?

Related:

–jeroen

Posted in Development, Excel, LifeHacker, Office, Power User, Software Development | Leave a Comment »

Editors (including visual studio code – VSCode): insert tab character manually – Stack Overflow

Posted by jpluimers on 2020/11/11

Sometimes you are in search of a real TAB character, as most editors (except a few like the ones for Golang) I bump into are space-based. A great answer at [WayBack] visual studio code – VSCode insert tab character manually – Stack Overflow:

Quick-and-dirty solution: Find a tab somewhere else, then copy-paste.

Chances are that you already have a tab character in the file you are editing, but if not you can generate one in another application or text editor.

You can also generate a tab programmatically in a bash shell with the following command (the brackets are optional):

echo -e [\\t]

For your more immediate needs, I have inserted a tab character below…

    There is a tab character between these brackets: [ ]

–jeroen

Posted in Development, Software Development, Visual Studio and tools, vscode Visual Studio Code | Leave a Comment »

Be careful changing the DataContext of a TRemotable

Posted by jpluimers on 2020/11/11

Still not sure why the RTL code is like this:

procedure TRemotable.SetDataContext(Value: TDataContext);
begin
  if (RemotableDataContext <> nil) and (RemotableDataContext = Self.DataContext) then
  begin
    TDataContext(RemotableDataContext).RemoveObjectToDestroy(Self);
  end;
  FDataContext := Value;
end;

It means that if you ever have to change the DataContext property from the default global RemotableDataContext, it will be removed, but not added to the new DataContext.

When you assign it nil (so you can dump it to JSON, which often is easier to read than XML), and back to the old value, this results in a memory leak:

function TNotificationKeyPortTypeImplementation.prematchChanged(const prematchChangedRequest: prematchChangedRequest): prematchChangedResponse;
var
  DataContext: TDataContext;
begin
  // ...
  DataContext := prematchChangedRequest.DataContext;
  try
    prematchChangedRequest.DataContext := nil; // otherwise the JSON serializer will stackoverflow because DataContext points back to the TRemotable instance.
    Result := Format('prematchChanged: prematchChangedRequest=%s', [TJson.ObjectToJsonString(prematchChangedRequest)]);
  finally
    // `prematchChangedRequest.DataContext := nil` removed `prematchChangedRequest` from `DataContext.FObjsToDestroy`
    DataContext.AddObjectToDestroy(prematchChangedRequest);
    prematchChangedRequest.DataContext := DataContext; // does not add `prematchChangedRequest` to `DataContext.FObjsToDestroy`
  end;
end;

or when you are outside an incoming SOAP call where DataContext might not be assigned at all:

function ToJSON(const Value: TRemotable): string;
var
  DataContext: TDataContext;
  RemotableDataContext: Pointer;
begin
  if Assigned(Value) then
  begin
    DataContext := Value.DataContext;
    try
      Value.DataContext := nil; // otherwise the JSON serializer will stackoverflow because DataContext points back to the TRemotable instance.
      Result := TJson.ObjectToJsonString(Value);
      Result := TRegExSanitiser.ReplaceSecretInText(Result, [rttJSON]);
    finally
      // `Value.DataContext := nil` removed `Value` from `DataContext.FObjsToDestroy`
      if Assigned(DataContext) then
      begin
        RemotableDataContext := GetRemotableDataContext();
        if Assigned(RemotableDataContext) and (RemotableDataContext = DataContext) then
          DataContext.AddObjectToDestroy(Value);
        Value.DataContext := DataContext; // does not add `Value` to `DataContext.FObjsToDestroy`
      end;
    end;
  end
  else
    Result := '';
end;

–jeroen

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

JSON to tabular format via JSONformatter.org and JSON2table.com

Posted by jpluimers on 2020/11/10

Two interesting sites to ease transforming JSON fragments in log-messages to a table system, for instance Excel.

  1. Paste the bits in [WayBack] Best JSON Pretty Print Online then fix any syntax errors.
  2. Copy from there to [WayBack] json2table.com and press the triangle button (run)
  3. Copy either the tabular or tree result to your favourite program.
  4. Format any numbers for readability. I really like the Custom format ##0.00E+00 that just shows the exponents in multiples of 3 (so kilo, mega, giga, etc)[WayBack] formatting – How can I format bytes a cell in Excel as KB, MB, GB etc? – Stack Overflow

This way I copied the example code into adjecent Excel areas, so I could compare the values and calculate memory increase of a Delphi application.

jeroen

Read the rest of this entry »

Posted in Development, JavaScript/ECMAScript, JSON, LifeHacker, Power User, Scripting, Software Development | Leave a Comment »

Git pushing to multiple remotes

Posted by jpluimers on 2020/11/10

I didn’t know there were multiple ways to push to multiple remotes.

[WayBack] github – Git – Pushing code to two remotes – Stack Overflow is intriguing as the accept answer shows one remote can have more than one URL, and you can push to all of them at the same time.

Most people just have multiple remotes with one URL per remote, and have a branch optionally track one remote brach: [WayBack] How can I tell a local branch to track a remote branch?

The other way around: you can find out which branch track remote branches as well: [WayBack] git – Find out which remote branch a local branch is tracking – Stack Overflow

–jeroen

 

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

Register and use a custom clipboard format in Delphi – twm’s blog

Posted by jpluimers on 2020/11/05

Cool post: [WayBack] Register and use a custom clipboard format in Delphi – twm’s blog.

It is about transmitting GPS (WGS 84) coordinates from one program to another via the clipboard.

One day I will find some time to dust off some draft clipboard posts that I have been dormant for too long.

These already got published:

Via [WayBack] I just now had the need to transmit GPS (WGS 84) coordinates from one program to another. First, I simply copied longitude and latitude separately using… – Thomas Mueller (dummzeuch) – Google+

–jeroen

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

Git history in Visual Studio Code

Posted by jpluimers on 2020/11/04

Out of the box, Visual Studio Code does allow you to pull from and commit/push to git repositories, but it has not much more git support.

These two marketplace extensions will help big time:

I like GitLens most as it covers so much more than just git history.

If you only need git history access, then you can use Git History as well.

More information and a better comparison:

–jeroen

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