Solved

How I make to test if the printer will go to print a report without giving error?

Posted on 2010-11-25
16
523 Views
Last Modified: 2012-05-10
Attention, my doubt is not if the printer is on line or off line, what I want to know I am if does not go to give error in the report when will be to print.

An example of error when printing is when the using one changes drive of the installed printer, then when it is ordered to print the error occurs. I want to detect this type of error before printing the report!
0
Comment
Question by:mccoymad
  • 7
  • 5
  • 3
  • +1
16 Comments
 
LVL 14

Expert Comment

by:systan
ID: 34215128
hi
try to drop TPrintDialog
if NOT printDialog1.execute then 

begin

     showmessage('NO printer selected');

end

else

begin

     showmessage('Starting to print');

end;

Open in new window

0
 
LVL 32

Expert Comment

by:ewangoya
ID: 34215133

uses
  WinSpool

function IsValidPrinter(const APrinterName: string): Boolean;
var
  prnHandle: THandle;
begin
  Result := OpenPrinter(PChar('APrinterName'), prnHandleHandle, nil);
  if Result then
    CloseHandle(prnHandle);
end;

0
 
LVL 32

Expert Comment

by:ewangoya
ID: 34215135
typo

uses
  WinSpool

function IsValidPrinter(const APrinterName: string): Boolean;
var
  prnHandle: THandle;
begin
  Result := OpenPrinter(PChar('APrinterName'), prnHandle, nil);
  if Result then
    CloseHandle(prnHandle);
end;

0
 
LVL 24

Expert Comment

by:jimyX
ID: 34215527
To be able to detect any error if the driver is corrupted or is missing files all you have to do is call GetMapMode and catch the error in Try-Except block.

The following code will validate the default printer.

uses Printers;

function IsDeviceValid():integer;
begin
  result := 0;
  if Printer.PrinterIndex < 0 then
    begin
      result := 0;
      Exit;
    end;
  try
    GetMapMode(Printer.Handle);
    result := 1;
  except
    Printer.PrinterIndex := -1;
    result := -1;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  if IsDeviceValid() = 1 then
    showmessage('Valid printer')
  else
    if IsDeviceValid() = 0 then
      showmessage('No printer available !')
    else
      showmessage('Printer error');
end;

Open in new window

0
 
LVL 24

Expert Comment

by:jimyX
ID: 34215539
This will validate a printer by passing its name:

uses Printers, Winspool;

function PrinterHandleByName(PrinterName:string):THandle;
begin
   Result:=0;
   if not OpenPrinter(PChar(PrinterName), result, nil) then
     RaiseLastOSError
   else
   begin
     ClosePrinter(result) ;
   end
end;

function IsDeviceValid(PrinterName:String):integer;
begin
  result := 0;
  if Printer.PrinterIndex < 0 then
    begin
      result := 0;
      Exit;
    end;
  try
    GetMapMode(PrinterHandleByName(PrinterName));
    result := 1;
  except
    Printer.PrinterIndex := -1;
    result := -1;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  if IsDeviceValid('YourPrinterName') = 1 then
    showmessage('Valid printer')
  else
    if IsDeviceValid() = 0 then
      showmessage('No printer available !')
    else
      showmessage('Printer error');
end;

Open in new window

0
 

Author Comment

by:mccoymad
ID: 34216910
No suggestion functioned!!

An example of error when printing: installs a virtual printer call PrimoPdf, www.primopdf.com , later it goes in Properties/Port and it modifies the PrimoPort port for LPT1. Now all time that will be to print a document in this printer will go to occur error in the impression!

Necessary to detect this type of error before printing the document

My Code

  function IsValidPrinter(const APrinterName: string): Boolean;
  var
    prnHandle: THandle;
  begin
    Result := OpenPrinter(PChar(APrinterName), prnHandle, nil);
    if Result then begin
      try
        getmapmode(prnHandle);
      except
        Result := False;
      end;
      ClosePrinter(prnHandle);
    end;  
  end;
0
 
LVL 24

Expert Comment

by:jimyX
ID: 34217211
>  No suggestion functioned!!
That is not a printer error.

I installed the PrimoPdf and did test it, and my findings was that, it is a problem of handling the print job and not a problem of sending the print job.

PrimoPdf requires manual processing of printer jobs. Whenever you print using the PrimoPdf it will not be processed until you press "Create PDF" then it will be processed.

Try that please.

PrimoPdf.JPG
0
 

Author Comment

by:mccoymad
ID: 34217224
You change PrimoPort port for LPT1 in Properties of print????
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:mccoymad
ID: 34217262
0
 
LVL 24

Expert Comment

by:jimyX
ID: 34217274
But PrimoPdf is different than the LPT1 actually the PrimoPdf is a converter so whenever you print something to it, that will be converted to PDF document but the process goes in printing operation.

What you are trying to do is not supported by PrimoPdf and can not be done. What you are trying to do is exactly like setting HP physical printer at the LPT1 port and change the port to Com1 which is not going to work because the connection and the configuration has been done to LPT1 (Printer Port) while the job will be sent to somewhere else.

You are trying to make PrimoPdf as an interface to the LPT1 printer (if there is any) that's what is giving you fail message when sending from PrimoPdf to LPT1 and not the printing itself.
0
 

Author Comment

by:mccoymad
ID: 34217313
I know this!!!

I want to know if does not go to give error in the report when I print. !!!
0
 

Author Comment

by:mccoymad
ID: 34217318
I want to test the printer before printing.
0
 

Author Comment

by:mccoymad
ID: 34217375
The alteration of the door of the PrimoPDF printer is an EXAMPLE that provokes error in the impression!

I do not want to make this, I said only one situation example that provokes the error in the impression!

Before printing the document, I need a routine that check if goes to occur error or not in the impression!

You understood?
0
 
LVL 24

Expert Comment

by:jimyX
ID: 34217678
I see. But your are doing a complicated approach which is checking the printer itself for printer error meanwhile you can check for print error, which occurs when performing printing command.

That error can be discovered when the print job is sent to the printer and the printer fails to handle it in Try-Except block.

For example that's possible when trying to print a QuickReport, after preparing some field in it, and catch the error that arise when printing, as follows:

try
    Form1.QuickRep.Print;
  except
    MessageDlg('Error printing.',mtError,[mbok],0);
  end;

Open in new window

0
 
LVL 32

Accepted Solution

by:
ewangoya earned 500 total points
ID: 34218536

Try this code, you may have to cancel the job if the printer is no good
uses
  WinSpool, Printers, Registry;

//you can use your own methods to get the printer port
function GetPrinterPort(const APrinterName: String): string;
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  with Reg do
  begin
    RootKey := HKEY_LOCAL_MACHINE;
     if OpenKey('\System\CurrentControlSet\Control\Print\printers\' + APrintername + '\', True) then
       if ValueExists('port') then
         Result := Readstring('port');
      CloseKey;
  end;
end;

//this is what determines if you can print
function GetJobStatus(APrinterHandle, AJobNumber: THandle): Boolean;
type
  TJobs = array [0..1000] of JOB_INFO_1;
  PJobs = ^TJobs;
var
  BytesNeeded, NumOfJobs, I: Cardinal;
  PJ: PJobs;
begin
  Result := True;
  EnumJobs(APrinterHandle, 0, 1000, 1, nil, 0, BytesNeeded, NumOfJobs);
  pJ := AllocMem(BytesNeeded);
  Result := EnumJobs(APrinterHandle, 0, 1000, 1, pJ, BytesNeeded, BytesNeeded, NumOfJobs);
  if Result and (NumOfJobs > 0) then
    for I := 0 to Pred(NumOfJobs) do
    begin
      if pJ^[i].JobId = AJobNumber then
      begin
        Result := (pJ^[i].Status AND $2) <> $2;
        if not Result then
          Exit;
      end;
    end;
end;

function IsValidPrinter(const APrinterName: string): Boolean;
var
  hPrn : THandle;
  DocInfo1 : TDocInfo1;
  PPort: string;
  PrintJob: THandle;
  PPrinter: PChar;
begin
  PPrinter := PChar(APrinterName);
  Result := OpenPrinter(PPrinter, hPrn,  nil);
  if Result then
  begin
    PPort := Trim(GetPrinterPort(APrinterName));
    if PPort = '' then
    begin
      Result := False;
      Exit;
    end;
    if PPort[Length(PPort)] = ':' then
      SetLength(PPort, Length(PPort) -1);

    DocInfo1.pDocName := 'Test';
    DocInfo1.pOutputFile := PChar(PPort);
    DocInfo1.pDataType := 'RAW';
    PrintJob := StartDocPrinter(hPrn, 1, @DocInfo1);
    Result := PrintJob <> 0;
    if Result then
    begin
      EndDocPrinter(hPrn); //if the printer is no good it will error out
      Sleep(1000); //delay a little longer to get status
      Result := GetJobStatus(hPrn, PrintJob);
      //if not result, you may need to cancel the printjob 
    end;
    ClosePrinter(hPrn)
  end;
end;

Open in new window

0
 

Author Closing Comment

by:mccoymad
ID: 34219431
Very good
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Suggested Solutions

This article explains how to create forms/units independent of other forms/units object names in a delphi project. Have you ever created a form for user input in a Delphi project and then had the need to have that same form in a other Delphi proj…
In this tutorial I will show you how to use the Windows Speech API in Delphi. I will only cover basic functions such as text to speech and controlling the speed of the speech. SAPI Installation First you need to install the SAPI type library, th…
This Micro Tutorial hows how you can integrate  Mac OSX to a Windows Active Directory Domain. Apple has made it easy to allow users to bind their macs to a windows domain with relative ease. The following video show how to bind OSX Mavericks to …
Hi friends,  in this video  I'll show you how new windows 10 user can learn the using of windows 10. Thank you.

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now