views:

1270

answers:

2

I have a Delphi web server providing some web services*. One of them is supposed to generate and return a PDF report.

The PDF creation is done with a QReport that is then exported into a PDF file with the ExportToFilter procedure.

The routine works fine when called from within an application, but when called behind a TIdTCPServer, it hangs and never finishes. Debugging it, I got tho the hanging point:

(note: I'm home right now and I don't have the source code. I'll try to reproduce quickrpt.pas' source as accurrate as I can remember).

procedure TCustomReport.ExportToFilter(TQRDocumentFilter filter);
  ...
  AProgress := TQRFormProgress.Create(Application); // Hangs on this line
  AProgress.Owner := QReport;
  if ShowProgress then AProgress.Show;
  QReport.Client := AProgress;
  ...

Searching the web, I found in this page (1) the suggestion to set ShowProgress to False, and edit the code so that it does not create the progress form when ShowProgress is set to false (apparently, this is due to QReport not being threadsafe).

So, I edited the code, and now I have this:

procedure TCustomReport.ExportToFilter(TQRDocumentFilter filter);
  ...
  if ShowProgress then
  begin
    AProgress := TQRFormProgress.Create(Application);
    AProgress.Owner := QReport;
    AProgress.Show;
    QReport.Client := AProgress
  end;
  ...

Now, the report comes out. But then the service gets to an Invalid Pointer Exception (which I can't trace). Following calls to the service complete successfully, but when I shut down the service** it starts whining again with Invalid Pointer Exceptions, then the "MyServer has commited an invalid action and must be closed" windows message, then again a couple of times more, then just the pointer exception, then comes to error 216 (which as far as I could find out, is related to Windows access permissions).

Thanks!

Update (jan 5): Thanks Scott W. for your answer. Indeed, after some research, I found another suggestion that only the main thread can access some components. So I set the QR code back to normal and called the main method from a Synchronize call inside a TThread (so that way the main thread would handle it). But I still get the same error.

You mention you were able to generate PDF as a service with QR 4. Maybe that's why it's not working for me, since I'm using QR 3. On the other hand, you don't mention if you're doing that behind a TIdTCPServer (which is my case, providing web services) or if you run it by itself (for instance, during a batch process).

Anybody knows whether my QR version might be the problem? Thanks!

* Running Delphi 7 and QuickReport 3 on a Windows XP SP2. The server is based on Indy.

** I have two versions of the server: a Windows application and a Windows Service. Both call the same inner logic, and the problem occurs with both versions.

Update (mar 8): After all, my problem was that my printing routine was in another dll, and the default memory management module is somewhat crappy. Setting the first uses of my .dpr to be ShareMem overrides the memory management module with Borland's implementation, and solved my problem.

uses
    ShareMem, ...

(1): http://coding.derkeiler.com/Archive/Delphi/borland.public.delphi.thirdpartytools.general/2006-09/msg00013.html

+1  A: 

I'm guessing that QReport.Client is used somewhere later in the code, and with your modified code no longer assigning it to AProgress, you end up with an error.

Are you sure that you have to modify the QuickReport source? I have used QuickReport in a Windows Service to generate a PDF file and then attach to email message and all worked fine without having to modify the QR source. I don't recall exactly which settings had to be made, but it was done with Delphi 6 and QR 4.06.

Scott W
Do you recall if you generate those PDF behind a TIdTCPServer (as in web services or a web server)? Thanks!
Pablo
No, we don't. The only network component involved in the service is the SMTP connection component.
Scott W
A: 

Did you resolve this? I have exactly the same problem with QuickReport and TIdTCPServer, except that I don't have the QR source code.

Yes, I finally solved it, through it came from a completely different approach.My problem was that my printing code was in another dll, and the default memory manager is somewath crappy. Setting the first USES in your dpr to be ShareMem solved my problem.
Pablo