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

Archiving Google Product Forums URLs

Posted by jpluimers on 2020/11/13

Archiving Google Product Forum URLs is a pain in the butt for a couple of reasons:

So the trick for saving is:

  1. Get from the /forum/#!topic/ based URL to the /d/topic/ based one
  2. Put it after the archive.is/?run=1&url=, then save

--jeroen

 

Posted in Conference Topics, Conferences, Event, Internet, InternetArchive, Power User, WayBack machine | Leave a Comment »

Apple M1 ARM based Mac as a developer: docker and brew will take a while to be working at all or supported

Posted by jpluimers on 2020/11/13

Important to consider as both a developer and end-user when switching architectures:

Is all my software working and supported on the new architecture.

For many Mac developers, at least docker and brew are important.

Bad news here:

  • Docker will likely take months before it runs, and then only support ARM images
  • Brew will likely take months to get supported.

Background links:

https://github.com/docker/for-mac/issues/4733

https://github.com/Homebrew/brew/issues/7857

Via:

https://twitter.com/IanColdwater/status/1326929654368792576

Oh, there is plenty more that does not work yet or never will:

https://twitter.com/craigstuntz/status/1328482376125657091

Apple MacBook Pro 13” M1 Review- Why You Might Want To Pass

https://www.forbes.com/sites/patrickmoorhead/2020/11/21/apple-macbook-pro-13-m1-reviewwhy-you-might-want-to-pass/amp/

Posted in Uncategorized | Leave a Comment »

Using both Google Fi and Google Voice means you need to use two Google accounts on the same phone

Posted by jpluimers on 2020/11/13

A while ago at [WayBack] The only bad thing about getting Google Fi is giving up Google Voice — Mike Elgan wrote

You can use Google Voice or you can use Google Fi, but you can’t use both. I just bought a Google Pixel 3 in order to move off AT&T and onto Google Fi fulltime. (We used to use Google Fi using my wife’s account, but only as a WiFi hotspot while traveling abroad.) It’s kind of a bummer, b

But the first comment has a solution that works, if you use two Google accounts that is:

I have Fi and use Google Voice on the same phone. I have to sign in to Voice with a separate Google account so there are some compromises but it works for how I use it.

–jeroen

Posted in Google, GoogleVoice, LifeHacker, Power User | Leave a Comment »

Chrome not asking to save or saving passwords? – Google Product Forums

Posted by jpluimers on 2020/11/13

From [Archive.is] Chrome not asking to save or saving passwords? – Google Product Forums

Hemanth M said:

After a lot of playing around, I’ve arrived at an elegant solution. Here are the steps:Steps to make Google Chrome offer to save (prompt) password for a particular site (for e.g abcd.com) and Auto-login the site with the credentials thus saved.

  1. Go to the given URL ‘abcd.com
  2. Right-click Page Info and disable ‘JavaScript’
  3. Reload the page.
  4. Enter the credentials (uid,pwd)
  5. A prompt appears to save password.
  6. Click on Save password.
  7. Auto-Login Extension bubble appears on this page.

At this point it is important because the extension ‘Auto-Login’ (like many other extensions) require JavaScript to be enabled.

  1. Re-enable the JavaScript for this page and reload the page.
  2. Now Click on the ‘Auto-Login’ bubble for remembering automatically logging into the site hereafter!

In my case, this was for ESXi credentials. Do not go the cheap way or revealing them inside javascript like these guys:

–jeroen

Posted in Chrome, Chrome, Google, Power User, Web Browsers | 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 »

Me starting to understand the real life meanings of Shim

Posted by jpluimers on 2020/11/12

The combination of being partially word blind and having learned English initially from my urge to understand computing books during my (Dutch) secondary education in the mid 1980s, I often have a gap between understanding “daily life” or “real life” English words, especially when they also have a meaning in the computing world.

So it took me a while to get the non-computing meaning of shim.

In computing, shim is used as word for tiny shell that separates two layers, which means my original association was with “sphere”.

Had I associated with an adapter or something that puts space between to layers, it would have been much easier to understand the “real life” meaning of a spacer shim.

Similarly, I had trouble understanding washer (which I associated with washing, and is right: it often means washing machine, but can also mean dish washer, which is an odd word for me as it washes much more than dishes). It took me much longer to get there is an additional meaning for a mechanical construction washer, which is a thin disc (so not a tube-like ring) often used as spacers, so in a sense similar to a shim.

In Dutch, I have the same problem with “wasmachine” (English washing machine) and “afwasmachine” (Dish washer).

To add to the confusion, hardware washers in Dutch are called rings.

–jeroen

All of the above links are from Wikipedia.

Posted in About, LifeHacker, Personal, Power User | 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 »