3

我有一个返回错误报告的应用程序。该应用程序是用 Delphi 2006 编写的,并在启动期间挂起。MadExcept 主线程堆栈如下所示。我怀疑没有默认打印机,但我无法在此处复制故障。

来自 MadExcept 的堆栈转储

有人见过这个问题吗?

WWPrintToPrinterOrPDFRoutines 单元的初始化部分

initialization
PagesRangeStartPage    := 1 ;
PagesRangeEndPage      := 999 ;
PrintRange             := prAll ;
PrintCopies            := 1 ;
PrintCollate           := false ;
InitialPrintPaperName  := 'A4' ;                                   

if (Printer.Printers.Count = 0) then    //  <--------- this causes the hang
    begin
    InitialPrintOrientation       := Printers.poPortrait ;
    end
else
    begin
    InitialPrintOrientation       := GetDefaultPrinterOrientation ;       
    InitialPrintPaperName         := GetDefaultPrinterPaperName ;         
    end ;

CurrentPreviewPage     := 1 ;
NDRMemoryStream        := TMemoryStream.Create ;

或拆卸:

    WWPrintToPrinterOrPDFRoutines.pas.682: PagesRangeStartPage    := 1 ;
    007C4404 C705EC8B81000100 mov [$00818bec],$00000001
    WWPrintToPrinterOrPDFRoutines.pas.683: PagesRangeEndPage      := 999 ;
    007C440E C705F08B8100E703 mov [$00818bf0],$000003e7
    WWPrintToPrinterOrPDFRoutines.pas.684: PrintRange             := prAll ;
    007C4418 C605F48B810001   mov byte ptr [$00818bf4],$01
    WWPrintToPrinterOrPDFRoutines.pas.685: PrintCopies            := 1 ;
    007C441F C705F88B81000100 mov [$00818bf8],$00000001
    WWPrintToPrinterOrPDFRoutines.pas.686: PrintCollate           := false ;
    007C4429 C605FC8B810000   mov byte ptr [$00818bfc],$00
    WWPrintToPrinterOrPDFRoutines.pas.687: InitialPrintPaperName  := 'A4' ;
    007C4430 B8288C8100       mov eax,$00818c28
    007C4435 BAC0447C00       mov edx,$007c44c0
    007C443A E82D1AC4FF       call @LStrAsg
    WWPrintToPrinterOrPDFRoutines.pas.689: if (Printer.Printers.Count = 0) then
    007C443F E8B0BCCDFF       call Printer
    007C4444 E89FB7CDFF       call TPrinter.GetPrinters   <----- HANG OCCURS HERE
4

1 回答 1

7

我认为您的程序没有任何问题,或者您可以更改任何内容以使其不会挂起。该系统的操作系统级别出现问题。

NdrClientCall2 函数是远程过程调用网络数据表示引擎的一部分,用于进行 RPC 和 DCOM 调用。

NtConnectPort 是一个连接端口对象的函数(这是一个基本的内核对象,例如互斥体或文件句柄)。端口由 LPC 的最低级别的窗口使用。

对 NtConnectPort 的调用将阻塞,直到服务器调用 NtCompleteConnectPort(对 NtConnectPort 的调用没有超时处理)。

所以你的问题是,winspool.drv 试图与同一台机器上的另一个进程建立 LPC 连接(我的猜测是 spoolsv.exe,打印机后台处理程序服务,但从提供的信息中无法判断)并且这个其他进程有创建了一个端口 (NtCreatePort) 但没有在其上调用 NtListenPort,或者当 NtListenPort 返回时未在其上调用 NtAcceptConnectPort 和 NtCompleteConnectPort。这可以防止在您的进程中调用 NtConnectPort 每次返回。

所以真正的问题在你的进程之外,无论端口的另一端属于什么进程。

于 2011-04-18T02:19:43.087 回答