Solved

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

Posted on 2010-11-25
16
519 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
How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

 

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

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Hello everybody This Article will show you how to validate number with TEdit control, What's the TEdit control? TEdit is a standard Windows edit control on a form, it allows to user to write, read and copy/paste single line of text. Usua…
In my programming career I have only very rarely run into situations where operator overloading would be of any use in my work.  Normally those situations involved math with either overly large numbers (hundreds of thousands of digits or accuracy re…
This video discusses moving either the default database or any database to a new volume.
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

757 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