In recent Delphi version, FastReport version 5 ships. But for parts of FastReport, it’s a trial. This includes the FastScript part. The trial is very close to the real FastReport 5 thing. So real that when you compile you don’t see a difference, not even when trial and official things are mixed.
The only difference is that the trial will have a ShowMessage result like this:
[Window Title] Fastscriptexecute [Content] Unregistered version of FastScript. [OK]
This occurred when I tried to move a the build process to a build server; a very tiny program will show this:
program FastScriptExecute; uses Vcl.Forms, fs_iinterpreter; {$R *.res} var fs: TfsScript; begin fs := TfsScript.Create(nil); try fs.Execute(); finally fs.Free(); end; end.
The build server had Delphi installed but not FastReports 5. I put all the sources in version control and fiddled with the project search paths until it built on the server.
Wrong!
Since the trial is so close to the real version, it will compile even if you don’t include all directories. In fact some permutations of the FastReports source and Delphi XE8 FastReports trial DUCs build perfectly fine.
Since the application at hand was a service with the reports running in a separate thread, the ShowMessage would just kill the thread without any exception.
It was worse because the same thread serviced all kinds of reports so they would run in a certain order and not take too much CPU at once when many reports were scheduled around the same moment in time. And it got even worse: breaking the thread would break all reporting as the thread was only instantiated once during service start up. There also wasn’t enough logging both for success and failure cases so zooming in on the problem took more time than needed: at first it was unclear when and for which report and report type the thread would terminate. Finally the test environment wasn’t equipped well enough to test the various permutations of scheduling, report types, report contents and data volumes.
Did I mention I inherited this project?
Finally I trimmed down the code to this little reproducible case:
In retrospect there should have been
- more logging
- a pool of reporting threads
- a better test environment
- a process that explains any modules in the MAP file not resulting in DCU files
Anyway: when debugging this a regular application, you see this:
The trial version is build like this (the code fragment is from an on-line FastScript 1.7 copy of fs_iinterpreter.pas):
But when you look at the official version, you see the below source code: it has a blank line where the conditional define check and ShowMessage was.
procedure TfsScript.Execute; begin FExitCalled := False; FTerminated := False; FIsRunning := True; FMainProg := True; try FStatement.Execute; finally FExitCalled := False; FTerminated := False; FIsRunning := False; end; end;
Under the hood the Delphi ShowMessage is redirected via various overloads of ShowMessagePos, MessageDlgPos, MessageDlgPosHelp and DoTaskMessageDlgPosHelp to TTaskMessageDialog.
The latter is incompatible with services likely in the same way it’s incompatible with DllMain (it calls TaskDialogIndirect which leads to havoc when there is no UI around – no coincidence it says “desktop apps only”)
–jeroen
Filed under: Delphi, Delphi XE8, Development, FastReport, Software Development
