Printer spooler hangs when printing multiple copies
Hi,
Several of our clients have reported the following problem:
- Print a report with multiple copies using the standard Delphi
TPrinterDialog. These printersettings are copied to the report and the
report does not show it's own printerdialog.
- The document is sent to the printer spooler where it hangs
indefinitely. It keeps showing the status "Sending document to printer"
- The problem occurs on multiple platforms using multiple printers.
- The systems affected do have a default printer selected.
- The problem seems to go away when printing only a single copy.
When I try to reproduce the problem and trace it, I can't. We are using
Delphi 2007 and ReportBuilder 11.08. Any and all help would be appreciated.
See below for the code used for printing the report.
with kind Regards,
Roald van Doorn.
Printing code:
ReportForMerge.DeviceType := dtPrinter;
ReportForMerge.AllowPrintToFile := False;
ReportForMerge.ShowPrintDialog := False;
ReportForMerge.ShowCancelDialog := False;
CopyPrinterSetup(Printer, ReportForMerge.PrinterSetup);
ReportForMerge.PrinterSetup.DocumentName := DocumentNaam;
ReportForMerge.Print;
procedure CopyPrinterSetup(ASource: TPrinter; ADest: TppPrinterSetup);
var
deviceBuffer: array[0..MAX_PATH] of Char;
driverBuffer: array[0..MAX_PATH] of Char;
portBuffer: array[0..MAX_PATH] of Char;
deviceModeHandle: Cardinal;
deviceMode: PDeviceMode;
binIndex: Integer;
capabilities: TppPrinterCapabilities;
begin
ADest.BinName := cDefault;
ADest.PrinterName := ASource.Printers[ASource.PrinterIndex];
ADest.Copies := ASource.Copies;
ADest.BinName := cDefault;
ASource.GetPrinter(@deviceBuffer, @driverBuffer, @portBuffer,
deviceModeHandle);
if deviceModeHandle <> 0 then
begin
deviceMode := GlobalLock(deviceModeHandle);
if Assigned(deviceMode) then
try
if (deviceMode^.dmFields and DM_DEFAULTSOURCE) > 0 then
begin
{ dmDefaultSource is almost never in the list that
DeviceCapabilities (and ultimately ReportBuilder) returns.
Workaround: let ReportBuilder return the right bin by
creating one. }
capabilities := ADest.PrinterInfo.Capabilities;
binIndex := capabilities.BinNames.IndexOf(DummyBin);
if binIndex > -1 then
begin
capabilities.Bins[binIndex] :=
IntTostr(deviceMode^.dmDefaultSource);
end else
begin
capabilities.BinNames.Add(DummyBin);
capabilities.Bins.Add(IntTostr(deviceMode^.dmDefaultSource));
end;
ADest.BinName := DummyBin;
end;
finally
GlobalUnlock(deviceModeHandle);
end;
end;
end;
Several of our clients have reported the following problem:
- Print a report with multiple copies using the standard Delphi
TPrinterDialog. These printersettings are copied to the report and the
report does not show it's own printerdialog.
- The document is sent to the printer spooler where it hangs
indefinitely. It keeps showing the status "Sending document to printer"
- The problem occurs on multiple platforms using multiple printers.
- The systems affected do have a default printer selected.
- The problem seems to go away when printing only a single copy.
When I try to reproduce the problem and trace it, I can't. We are using
Delphi 2007 and ReportBuilder 11.08. Any and all help would be appreciated.
See below for the code used for printing the report.
with kind Regards,
Roald van Doorn.
Printing code:
ReportForMerge.DeviceType := dtPrinter;
ReportForMerge.AllowPrintToFile := False;
ReportForMerge.ShowPrintDialog := False;
ReportForMerge.ShowCancelDialog := False;
CopyPrinterSetup(Printer, ReportForMerge.PrinterSetup);
ReportForMerge.PrinterSetup.DocumentName := DocumentNaam;
ReportForMerge.Print;
procedure CopyPrinterSetup(ASource: TPrinter; ADest: TppPrinterSetup);
var
deviceBuffer: array[0..MAX_PATH] of Char;
driverBuffer: array[0..MAX_PATH] of Char;
portBuffer: array[0..MAX_PATH] of Char;
deviceModeHandle: Cardinal;
deviceMode: PDeviceMode;
binIndex: Integer;
capabilities: TppPrinterCapabilities;
begin
ADest.BinName := cDefault;
ADest.PrinterName := ASource.Printers[ASource.PrinterIndex];
ADest.Copies := ASource.Copies;
ADest.BinName := cDefault;
ASource.GetPrinter(@deviceBuffer, @driverBuffer, @portBuffer,
deviceModeHandle);
if deviceModeHandle <> 0 then
begin
deviceMode := GlobalLock(deviceModeHandle);
if Assigned(deviceMode) then
try
if (deviceMode^.dmFields and DM_DEFAULTSOURCE) > 0 then
begin
{ dmDefaultSource is almost never in the list that
DeviceCapabilities (and ultimately ReportBuilder) returns.
Workaround: let ReportBuilder return the right bin by
creating one. }
capabilities := ADest.PrinterInfo.Capabilities;
binIndex := capabilities.BinNames.IndexOf(DummyBin);
if binIndex > -1 then
begin
capabilities.Bins[binIndex] :=
IntTostr(deviceMode^.dmDefaultSource);
end else
begin
capabilities.BinNames.Add(DummyBin);
capabilities.Bins.Add(IntTostr(deviceMode^.dmDefaultSource));
end;
ADest.BinName := DummyBin;
end;
finally
GlobalUnlock(deviceModeHandle);
end;
end;
end;
This discussion has been closed.
Comments
If your users use the built-in print dialog that is included with
ReportBuilder, do they still get the issue? If not, I would suggest
taking a look at our printer code and seeing how it differs from yours
below.
Looking at your code, my guess is that an incorrect/invalid bin or
printer name is being assigned. You might also try delegating the
copies to the printer by setting the PrinteSetup.DelegateCopies property
to True.
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
suddenly starts.
Op 29-3-2012 15:39, Roald van Doorn schreef:
We finally came around to deploying your suggestion about DelegateCopies
to our customer. He now reports that the print(s) finish completely, but
the task will remain in the printspooler, preventing other applications
from printing.
To clarify:
At some point in the customer's process he will press print. Based upon
a selection, one or more reports are printed. Since we don't want to
present our customer with more than 1 printdialog, there is a single
printdialog shown and these settings are copied to the different
reports. At this moment I have no possibility to replace this
TPrintDialog with a call to the ReportBuilder printdialog. Also, before
setting the DelegateCopies property to True, the customer reported that
even though the Print spooler seemed to be hanging, actually closing the
application made the prints come out anyway and freed up the spooler.
All printcalls are made to a datamodule wich is created before the print
and destroyed immediately after.
Are there any other suggestions you might have that we could try?
Thanks in advance.
Kind regards,
Roald van Doorn
Op 29-3-2012 15:54, Nico Cizik (Digital Metaphors) schreef:
There still must be some setting causing this hanging. My suggestion
would be to simplify your code as much as possible then have your
customer print to try to isolate the problem.
If perhaps, your customer only prints one report so the settings are not
copied, do they still get the problem?
Nico Cizik
Digital Metaphors
http://www.digital-metaphors.com
detail rows to fill the page, and have only the subreport on the next page
(no details), then just spool. Closing the exe would also clear the spooler.
More or less detail rows worked fine.
Through trial and error, I set the ppDetailBand.PrintHeight to phStatic, and
that fixed my problem.