使用Delphi Web Server后面的快速报告生成PDF

时间:2021-06-29 21:10:45

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

我有一个Delphi Web服务器提供一些Web服务*。其中一个应该生成并返回PDF报告。

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

PDF创建使用QReport完成,然后使用ExportToFilter过程将其导出为PDF文件。

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:

从应用程序内部调用时,例程工作正常,但是当在TIdTCPServer后面调用时,它会挂起并且永远不会完成。调试它,我得到了悬挂点:

(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).

(注意:我现在回家了,我没有源代码。我会尝试重现quickrpt.pas'来源,因为我记得很复杂)。

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).

搜索网页时,我在此页面(1)中找到了将ShowProgress设置为False的建议,并编辑代码,以便在ShowProgress设置为false时不会创建进度表单(显然,这是由于QReport不是线程安全的)。

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).

现在,报告出来了。但随后服务变为无效指针异常(我无法追踪)。在成功完成对服务的调用之后,但是当我关闭服务时**它再次使用无效指针异常开始抱怨,然后“MyServer提交了无效操作并且必须关闭”窗口消息,然后再次多次,然后只是指针异常,然后来到错误216(据我所知,这与Windows访问权限有关)。

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.

更新(1月5日):感谢Scott W.的回答。实际上,经过一些研究,我发现了另一个建议,即只有主线程才能访问某些组件。所以我将QR码恢复正常,并通过TThread内的Synchronize调用调用main方法(这样主线程就可以处理它)。但我仍然得到同样的错误。

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).

你提到你能够用QR 4生成PDF作为服务。也许这就是为什么它不适合我,因为我使用的是QR 3.另一方面,你没有提到你是否正在这样做TIdTCPServer(这是我的情况,提供Web服务)或者您自己运行它(例如,在批处理过程中)。

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

谁知道我的QR版本是否可能出现问题?谢谢!

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

*在Windows XP SP2上运行Delphi 7和QuickReport 3。该服务器基于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.

**我有两个版本的服务器:Windows应用程序和Windows服务。两者都调用相同的内部逻辑,并且两个版本都会出现问题。

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.

更新(3月8日):毕竟,我的问题是我的打印例程在另一个dll中,默认的内存管理模块有点蹩脚。将我的.dpr的第一次使用设置为ShareMem会使用Borland的实现覆盖内存管理模块,并解决了我的问题。

uses
    ShareMem, ...

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

1 个解决方案

#1


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.

我猜测QReport.Client会在代码中的某个地方使用,并且修改后的代码不再将其分配给AProgress,最终会出现错误。

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.

您确定必须修改QuickReport源吗?我在Windows服务中使用QuickReport生成PDF文件,然后附加到电子邮件消息,所有工作正常,无需修改QR源。我不记得究竟要做哪些设置,但它是用Delphi 6和QR 4.06完成的。

#1


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.

我猜测QReport.Client会在代码中的某个地方使用,并且修改后的代码不再将其分配给AProgress,最终会出现错误。

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.

您确定必须修改QuickReport源吗?我在Windows服务中使用QuickReport生成PDF文件,然后附加到电子邮件消息,所有工作正常,无需修改QR源。我不记得究竟要做哪些设置,但它是用Delphi 6和QR 4.06完成的。