我使用下面的代码来防止有人试图打印但没有默认打印机设置时发生异常。我收到了一位用户使用该软件远程使用该软件的报告,该用户使用网络打印机作为默认打印机。它在调用GetPrinter时引发异常,并显示消息“当前没有选择默认打印机”。从其他应用程序打印时没有问题。这会出什么问题?
function CheckForDefaultPrinter: boolean;
var
FDevice: PChar;
FDriver: PChar;
FPort: PChar;
FHandle: THandle;
CurrentPrinterName: string;
begin
//ensure default printer selected - bypass printer.pas bug
Printer.PrinterIndex := Printer.PrinterIndex;
GetMem (FDevice, 255);
GetMem (FDriver, 255);
GetMem (FPort, 255);
try
try
Printers.Printer.GetPrinter(FDevice, FDriver, FPort, FHandle);
except
on E:Exception do
ShowMessage(E.Message);
end;
CurrentPrinterName := FDevice;
finally
if FDevice <> nil then FreeMem (FDevice, 255);
if FDriver <> nil then FreeMem (FDriver, 255);
if FPort <> nil then FreeMem (FPort, 255);
end;
if CurrentPrinterName = '' then
begin
MessageDlg('You do not have a default printer defined.' +
#13#13 + 'Please select a printer before running a report.'+
#13#13 + 'Or the default printer name is blank. Please assign the printer a name.',
mtError,[mbOK],0);
Result:= False;
end
else
Result:= True;
end;
答案 0 :(得分:2)
错误发生在您发布的代码可以检查之前,因为它在第一次访问Printer
时失败。
在尝试使用全局Printer
之前,您应该直接使用WinAPI GetDefaultPrinter函数来查看是否存在默认打印机。这是一个示例控制台应用程序(使用比最近版本的Delphi中包含的函数更容易的声明)来演示如何执行此操作。该示例在XE 10 Seattle中编译,并在Windows 7 64位上进行了测试。
program Project1;
{$APPTYPE CONSOLE}
uses
System.SysUtils, WinAPI.Windows;
function GetDefaultPrinter(Buffer: PChar; var BufferSize: DWord): BOOL; stdcall;
external 'winspool.drv' name 'GetDefaultPrinterW'; // GetDefaultPrinterA on pre-Unicode Delphi versions
var
Buff: string;
BuffSize, Err: DWord;
begin
// Get size of buffer needed.
GetDefaultPrinter(nil, BuffSize);
SetLength(Buff, BuffSize);
// If this call fails, and GetLastError returns
// ERROR_FILE_NOT_FOUND, there is no default printer assigned.
if GetDefaultPrinter(PChar(Buff), BuffSize) then
WriteLn('Default printer: ', Buff)
else
begin
Err := GetLastError();
if Err = ERROR_FILE_NOT_FOUND then
WriteLn('No default printer assigned')
else
WriteLn('Failed. Error: ', Err);
end;
ReadLn;
end.
答案 1 :(得分:0)
在Windows上,您可以假设如果有超过0(零)个打印机,则有一个默认打印机。 除非您的应用程序作为服务运行,否则此配置是安全的。
所以你需要的就是:
if (Printer.Printers.Count=0) then
ShowMessage('Please install a printer before attempting to print.');
在访问Printer对象上的大多数其他属性/方法之前,您需要进行此检查。
如果您的应用程序作为服务运行,则不会有默认打印机。这里PrinterIndex将为-1,直到您在代码中分配值。
答案 2 :(得分:-2)
我用Delphi XE6,Win7Pro测试了你的代码。刚换了一行
GetMem (FPort, 255);
try
try
Printer.GetPrinter(FDevice, FDriver, FPort, FHandle); // HERE
except
on E:Exception do
ShowMessage(E.Message);
end;
默认使用联网打印机,即使拔下电缆也是如此。