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 ‘Delphi’ Category

When a Delphi TCP server causes sudden EIdConnClosedGracefully Exceptions on the client

Posted by jpluimers on 2018/09/19

I always forget which sides of the connection throw this error, but the client side does as explained in [WayBackdelphi – Troubleshooting EIdConnClosedGracefully Exceptions? – Stack Overflow by [WayBackRemy Lebeau the main Indy contributor:

EIdConnClosedGracefully means the other party … has disconnected its end of the connection. Once that exception has been raised, you cannot send more data to the other party. You must reconnect first.

Read the rest of this entry »

Posted in Delphi, Development, Software Development | 2 Comments »

I tend to forget there is a record intialiser TPair.Create(Key, Value) – via: delphi – TDictionary populated during create example code – Stack Overflow

Posted by jpluimers on 2018/09/18

I tend to forget that since TPair – introduced in Delphi 2009 – has had a TPair.Create(Key, Value)record initialiser since Delphi 2010, though only fully documented since Delphi XE4:

With some spart short methods, Cosmin Prund shows a really nice helper at [WayBack] delphi – TDictionary populated during create example code – Stack Overflow allowing a call like this:

  with TDictHelper<Integer, string> do
    Dict := Make([P(1, 'one'), P(2, 'two')]);

His answer has all the details (including describing the pros and conse), so here is only the helper:

uses
  SysUtils, Generics.Collections;

type
  TDictHelper<Key, Value> = class
  public
    class function P(const K:Key; const V:Value): TPair<Key, Value>;
    class function Make(init: array of TPair<Key, Value>): TDictionary<Key, Value>;overload;
    class function Make(KeyArray: array of Key; ValueArray: array of Value): TDictionary<Key, Value>;overload;
  end;

{ TDictHelper<Key, Value> }

class function TDictHelper<Key, Value>.Make(init: array of TPair<Key, Value>): TDictionary<Key, Value>;
var P: TPair<Key, Value>;
begin
  Result := TDictionary<Key, Value>.Create;
  for P in init do
    Result.AddOrSetValue(P.Key, P.Value);
end;

class function TDictHelper<Key, Value>.Make(KeyArray: array of Key;
  ValueArray: array of Value): TDictionary<Key, Value>;
var i:Integer;
begin
  if Length(KeyArray) <> Length(ValueArray) then
    raise Exception.Create('Number of keys does not match number of values.');
  Result := TDictionary<Key, Value>.Create;
  for i:=0 to High(KeyArray) do
    Result.AddOrSetValue(KeyArray[i], ValueArray[i]);
end;

class function TDictHelper<Key, Value>.P(const K: Key;
  const V: Value): TPair<Key, Value>;
begin
  Result := TPair<Key, Value>.Create(K, V);
end;

–jeroen

Posted in Conference Topics, Conferences, Delphi, Development, Event, Software Development | 7 Comments »

YouTube video how to use DDetours library to hook Win32 API in Delphi

Posted by jpluimers on 2018/09/18

via [WayBack] Just was sneaking around YouTube and found this video showing how to use DDetours library to hook Win32 api. – Mahdi Safsafi – Google+

–jeroen

Read the rest of this entry »

Posted in Delphi, Development, Software Development | 3 Comments »

chrisrolliston/CCR.PrefsIniFile: TCustomIniFile decendants for Delphi wrapping the Android, iOS and OS X Preferences APIs

Posted by jpluimers on 2018/09/13

If you need cross platform settings storage: [WayBackchrisrolliston/CCR.PrefsIniFile: TCustomIniFile decendants for Delphi wrapping the Android, iOS and OS X Preferences APIs

Via: [WayBack] In my application I use System.Win.Registry unit file to read or write to Windows Registry. Now that I have added MAC paltform I need an equivalent method to edit the plist file… – Dimitra Ger – Google+

–jeroen

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

TIdHTTPWebBrokerBridge example for a standalone Indy based SOAP service

Posted by jpluimers on 2018/09/12

Since I tend to forget what bits and pieces are needed for TIdHTTPWebBrokerBridge, the below code piece from:

The [WayBack] WebReq.WebRequestHandler Function returns a reference to the global [WayBackTWebRequestHandler object. This object manages all the Web modules in the application, and creates Web request and response objects when the application receives HTTP request messages: TWebRequestHandler keeps a pool of active Web modules. In response to a request from the application, TWebRequestHandler creates a request object and assigns it to one of the active Web modules.

The code below is the Indy counterpart of hooking up a classic WebSnap WebBroker (you could also hook the Web.WebBroker.Application.WebModuleClass to TMyWebModule instead of the WebRequestHandler.WebModuleClass, as Web.WebBroker.Application.WebModuleClass is a TWebApplication which inherits from TWebRequestHandler).

Read the rest of this entry »

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

delphi – How to make a combo box with fulltext search autocomplete support? – Stack Overflow

Posted by jpluimers on 2018/09/12

Interesting solutions based on the TLama first answer at [WayBackdelphi – How to make a combo box with fulltext search autocomplete support? – Stack Overflow

Via: [WayBack] Nice solution by TLama – Thomas Mueller (dummzeuch) – Google+

–jeroen

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

Delphi 10 Seattle and up try “recover” unchanged files in the `$(BDS)` tree

Posted by jpluimers on 2018/09/11

Every now – after some period of inactivity – I get an error like this when not having changed the file at all:

---------------------------
Error
---------------------------
Cannot create file "C:\Program Files (x86)\Embarcadero\Studio\18.0\Source\DUnit\src\__recovery\GUITestRunner.pas". Het systeem kan het opgegeven pad niet vinden.
---------------------------
OK Details >> 
---------------------------

This has been present since ever since Delphi 10 Seattle introduced the “recovery” feature on unchanged files in a read-only directory tree like for instance $(BDS).

It assumes the __recovery subdirectory has been created (which it cannot, but never raised an error about), then barfs when it cannot find the directory.

This is a classic example of “nice idea, bad execution, not caught by thinking through all the test cases”.

I think one of the roles played, is that cursor movements are part of the undo/redo stack. My suspicion is that this raises a “changed” flag, where in fact the file is unmodified.

Het systeem kan het opgegeven pad niet vinden. is the Dutch version of ERROR_PATH_NOT_FOUND error code 0x03 English The system cannot find the path specified.

Related:

–jeroen

Read the rest of this entry »

Posted in Delphi, Development, Software Development | 2 Comments »

Delphi XE6 and up regression: “‘9999-12-31 23:59:59,1000’ is not a valid date and time” when passing a SOAP message with 9999-11-31T23:59:59.9999999; QC144171

Posted by jpluimers on 2018/09/06

A valid SOAP message with <urn:timeStamp>9999-11-31T23:59:59.9999999</urn:timeStamp> in a xs:dateTime field return '9999-12-31 23:59:59,1000' is not a valid date and time from a Delphi application with this SOAP response:

<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/">
  <SOAP-ENV:Body>
    <SOAP-ENV:Fault>
      <faultcode>SOAP-ENV:Server</faultcode>
      <faultstring>'9999-12-31 23:59:59,1000' is not a valid date and time</faultstring>
      <faultactor/>
    </SOAP-ENV:Fault>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

The reason is this exception:

exception class EConvertError with message ''9999-12-31 23:59:59,1000' is not a valid date and time'.

This is from a .NET based test case passing in timeStamp = DateTime.MaxValuewhich is handled perfectly fine by other SOAP web services tested.

I know about different resolutions of time stamps, but would never expect the 999.9999 milliseconds to be rounded up to 1000 as it is always safer to truncated away from an upper limit.

A test using Soap UI [WayBack] with this parameter finally worked (max 3 digits second fraction):

<urn:timeStamp>9999-12-31T23:59:59.999</urn:timeStamp>

The true origin of problem is in this method in the Soap.XSBuiltIns unit which has been unchanged since at least Delphi 7:

function TXSBaseTime.GetMilliSecond: Word;
begin
  Result := Round(FractionalSeconds*1000);
end;

The problem exposed itself because as of Delphi XE6 the core of function TXSBaseCustomDateTime.GetAsDateTime piece was changed from

Result := EncodeDateTime(Year, Month, Day, Hour, Minute, Second, 0);

to

Result := EncodeDateTime(Year, Month, Day, Hour, Minute, Second, Millisecond);

A combination of lack of test cases and understanding XML specifications failed to reveal this bug.

The standards specify (among others):

  • '.' s+ (if present) represents the fractional seconds;
    The above is not limiting the amount of digits, not talking about milliseconds either.
  • All ·minimally conforming· processors ·must· support year values with a minimum of 4 digits (i.e., YYYY) and a minimum fractional second precision of milliseconds or three decimal digits (i.e. s.sss). However, ·minimally conforming· processors ·may· set an application-defined limit on the maximum number of digits they are prepared to support in these two cases, in which case that application-defined maximum number ·must· be clearly documented.
    Delphi not only limits the fractional second precission, it changes the limit over time and does not document the limit. Three strikes…
  • s -- represents a digit used in the time element "second". The two digits in a ss format can have values from 0 to 60. In the formats described in this specification the whole number of seconds ·may· be followed by decimal seconds to an arbitrary level of precision. This is represented in the picture by "ss.sss". A value of 60 or more is allowed only in the case of leap seconds.
    Given buggy the fractional second handling through milliseconds, the leap second handling is ripe for a test case as well.
    Strictly speaking, a value of 60 or more is not sensible unless the month and day could represent March 31, June 30, September 30, or December 31 in UTC. Because the leap second is added or subtracted as the last second of the day in UTC time, the long (or short) minute could occur at other times in local time. In cases where the leap second is used with an inappropriate month and day it, and any fractional seconds, should considered as added or subtracted from the following minute.

The reproduction is quite simple:

Read the rest of this entry »

Posted in .NET, C#, Conference Topics, Conferences, Delphi, Development, Event, SOAP/WebServices, Software Development, XML, XML/XSD | Leave a Comment »

Delphi – Defer defines the “postpone procedure” pattern to execute code at the end of a method

Posted by jpluimers on 2018/09/06

Last year, I stumbled upon [WayBack] Defer defines the “postpone procedure” pattern, this postpone should schedule a “procedure: TProc” to run it after the end of the caller method… – Cesar Romero – Google+ that points to this repository:

https://github.com/cesarliws/foundation-4-delphi

Some people like this usage of the RAII pattern, but I do like it even though I do not use it very often. The implementation better than my TAnonymousMethodMemento in Delphi: a memento that executes any code at end of method for various reasons:

Now the documentation could use more English (some of it is in Portuguese).

–jeroen

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

Some search links on Delphi and C# WSDL imports I need to investigate further

Posted by jpluimers on 2018/09/05

Sometimes, the Delphi WSDL importer imports fine, but the generated code does not accept test cases sent by other tools.

Below are some links for messages and comment fragments that I want to investigate further.

I have included the .NET message, because my experience is that searching on those gives more accurate results for something that could be broken in more than one environment.

Based on those:

Some on-line tools prefer the WSDL to be in one document, but a lot of WSDL documents use import and or include features, so here are some links on that too:

Bruneau Babet correctly informed me that – though Delphi SOAP clients support both document literal and RPC encoded – Delphi SOAP servers cannot support document literal, as they can only support RPC encoded. Through that I found

  • [WayBack] Apache CXF — WSDLValidator
    • Check the WSDL document for XML well-formedness.
    • Validate the WSDL document against its XML schema.
    • Validate the WSDL document using some of the semantic rules defined in the WSDL specification.
    • Validate the WSDL document against custom validation rules, such as those defined by the Web Services Interoperability (WS-I) organization (i.e. WS-I Basic Profile rules).
    • Validate the WSDL against strange exceptions, incorrectly generated code and general bad WSDL issues.

Back on those days, the big plan was to move everything Delphi to the .NET platform which supports both document literal and RPC encoded.

All in all, document literal has been on the radar with the Delphi R&D team since at least 2009, and nothing has been done.

References:

I looks like a wsdl message request part entries need to be named parameters for some tooling to correctly infer document/literal in a wrapped way. Some links for further research on this:

When you are surely running SOAP over HTTP, you can use this small class to raise exceptions which automatically get translated into SOAP Faults having the right return code using a trick I bumped into a few years ago from [WayBack] web services – Accessing the original TWebRequest object in a Delphi SOAP Server – Stack Overflow:

unit SoapFaultWithHttpCodeExceptionUnit;

interface

uses
  System.SysUtils;

type
  ESoapFaultWithHttpCodeException = class(Exception)
  strict private
    FHttpStatusCode: Integer;
  public
    constructor Create(const AHttpStatusCode: Integer);
    property HttpStatusCode: Integer read FHttpStatusCode;
  end;

implementation

uses
  Winapi.WinHTTP,
  Soap.WebBrokerSOAP,
  Web.HTTPApp,
  IdCustomHTTPServer;

constructor ESoapFaultWithHttpCodeException.Create(const AHttpStatusCode: Integer);
var
  IdHTTPResponseInfo: TIdHTTPResponseInfo;
  ReasonString: string;
  WebDispatcher: IWebDispatcherAccess;
begin
  IdHTTPResponseInfo := TIdHTTPResponseInfo.Create(nil, nil, nil);
  try
    FHttpStatusCode := AHttpStatusCode;
    IdHTTPResponseInfo.ResponseNo := AHttpStatusCode;
    ReasonString := Format('%d: %s', [AHttpStatusCode, IdHTTPResponseInfo.ResponseText]);
    inherited Create(ReasonString);

    // https://stackoverflow.com/questions/10405227/accessing-the-original-twebrequest-object-in-a-delphi-soap-server
    if Supports(GetSOAPWebModule, IWebDispatcherAccess, WebDispatcher) then
    begin
      WebDispatcher.Response.StatusCode := HTTP_STATUS_SERVER_ERROR;
      WebDispatcher.Response.ReasonString := ReasonString;
    end

  finally
    IdHTTPResponseInfo.Free;
  end;
end;

end.

jeroen

Read the rest of this entry »

Posted in .NET, C#, Conference Topics, Conferences, Delphi, Development, Event, SOAP/WebServices, Software Development, XML/XSD | Leave a Comment »