Delphi TPrinters.GetPrinters呼叫挂起

时间:2011-04-18 00:25:46

标签: delphi startup hang delphi-2006 printers

我有一个已经返回错误报告的应用。该应用程序是用Delphi 2006编写的,并在启动时挂起。 MadExcept主线程堆栈如下所示。我怀疑没有默认打印机,但我不能在这里复制错误。

Stack dump from 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

1 个答案:

答案 0 :(得分:7)

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

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

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

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

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

所以真正的问题是在你的过程之外,在端口的另一边属于的任何过程中。