Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Using GetPrinter with PRINTER_INFO_2 to obtain printer status

1,376 views
Skip to first unread message

GF

unread,
Feb 6, 2002, 5:51:27 AM2/6/02
to
Hi,

I am using GetPrinter and structure 2 (PRINTER_INFO_2) in an attempt to find
the current status of a printer prior to performing a print.

However, while the function returns indicating succes, by both filling the
structure with reasonable info and returning a non zero value, the structure
member Status has the value 0. Which is not listed for any of the
PRINTER_STATUS constants in winspool.h

The driver is set up in bidirectional mode and the cable is bidirectional.

Does anyone know if there are any limitations to this functionality?

gf


John Hornick [MS]

unread,
Feb 6, 2002, 9:15:44 AM2/6/02
to
Hi,

Please see the following KB article:
Q160129 HOWTO: Get the Status of a Printer and a Print Job

Thanks,
- John
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.

Chris Ward

unread,
Feb 18, 2002, 6:58:32 AM2/18/02
to
Hi,

I read the paper Q160129 and implemented it myself such that when a job is
sent to the printer (and for a time after it has printed), I periodically
(every 20mS) check to see if the printer is in an error state using
GetPrinter, this continues to return 0. I'm writing an application where it
is absolutly critical that print jobs, print as expected, the plan was that
any error occuring around the time of doing a print job will result in an
error stating that there is a possibility the job has not printed. The
operator would therefore check the printer and re-resend the jobs to print.

Any advice you could give me on getting a printer's status would be very
much grately appreciated

I include below my investigating code:

int PrinterStatus()
{
HANDLE hPrinter;
unsigned char *Printer_Info_2_Buffer = NULL;
PRINTER_INFO_2 *Printer_Info_2 = NULL;
unsigned long bNeeded;
unsigned long PrinterStatus;

if (!(OpenPrinter(PRINTER,&hPrinter,NULL)))
{
MessageBox(NULL, "Failed To Open Printer\n", "", 0);
}
else
{
while(true)
{

GetPrinter(
hPrinter, // handle to printer
2, // we want level 2 info i.e. very detailed
Printer_Info_2_Buffer, // printer information buffer
0, // size of buffer zero initially
&bNeeded); // bytes received or required

Printer_Info_2_Buffer = (unsigned char *)malloc(bNeeded);

if (GetPrinter(
hPrinter, // handle to printer
2, // we want level 2 info i.e. very detailed
Printer_Info_2_Buffer, // printer information buffer
bNeeded, // size of buffer
&bNeeded) // bytes received or required
!= 0)
{
// Success
Printer_Info_2 = (PRINTER_INFO_2 *)Printer_Info_2_Buffer;

PrinterStatus = Printer_Info_2->Status;

if (PrinterStatus & PRINTER_STATUS_BUSY) printf("The printer is
busy.\n");
if (PrinterStatus & PRINTER_STATUS_DOOR_OPEN) printf("The printer door
is open.\n");
if (PrinterStatus & PRINTER_STATUS_ERROR) printf("The printer is in an
error state.\n");
if (PrinterStatus & PRINTER_STATUS_INITIALIZING) printf("The printer is
initializing.\n");
if (PrinterStatus & PRINTER_STATUS_IO_ACTIVE) printf("The printer is in
an active input/output state.\n");
if (PrinterStatus & PRINTER_STATUS_MANUAL_FEED) printf("The printer is
in a manual feed state.\n");
if (PrinterStatus & PRINTER_STATUS_NO_TONER) printf("The printer is out
of toner.\n");
if (PrinterStatus & PRINTER_STATUS_NOT_AVAILABLE) printf("The printer is
not available for printing.\n");
if (PrinterStatus & PRINTER_STATUS_OFFLINE) printf("The printer is
offline.\n");
if (PrinterStatus & PRINTER_STATUS_OUT_OF_MEMORY) printf("The printer
has run out of memory.\n");
if (PrinterStatus & PRINTER_STATUS_OUTPUT_BIN_FULL) printf("The
printer's output bin is full.\n");
if (PrinterStatus & PRINTER_STATUS_PAGE_PUNT) printf("The printer
cannot print the current page.\n");
if (PrinterStatus & PRINTER_STATUS_PAPER_JAM) printf("Paper is jammed
in the printer.\n");
if (PrinterStatus & PRINTER_STATUS_PAPER_OUT) printf("The printer is
out of paper.\n");
if (PrinterStatus & PRINTER_STATUS_PAPER_PROBLEM) printf("The printer
has a paper problem.\n");
if (PrinterStatus & PRINTER_STATUS_PAUSED) printf("The printer is
paused.\n");
if (PrinterStatus & PRINTER_STATUS_PENDING_DELETION)printf("The printer
is deleting a print job.\n");
if (PrinterStatus & PRINTER_STATUS_POWER_SAVE) printf("The printer is
in power save mode.\n");
if (PrinterStatus & PRINTER_STATUS_PRINTING) printf("The printer is
printing.\n");
if (PrinterStatus & PRINTER_STATUS_PROCESSING) printf("The printer is
processing a print job.\n");
if (PrinterStatus & PRINTER_STATUS_SERVER_UNKNOWN) printf("The printer
status is unknown.\n");
if (PrinterStatus & PRINTER_STATUS_TONER_LOW) printf("The printer is
low on toner.\n");
if (PrinterStatus & PRINTER_STATUS_USER_INTERVENTION)printf("The printer
has an error that requires the user to do something.\n");
if (PrinterStatus & PRINTER_STATUS_WAITING) printf("The printer is
waiting.\n");
if (PrinterStatus & PRINTER_STATUS_WARMING_UP) printf("The printer is
warming up.\n");


}
else
{
// Failure
MessageBox(NULL, "Failed To Get Printer\n", "", 0);
}

free(Printer_Info_2_Buffer);

Sleep(2);

}

}

return 0;
}


"John Hornick [MS]" <JohnH...@online.microsoft.com> wrote in message
news:<0M3eTjxrBHA.1364@cpmsftngxa09>...


"John Hornick [MS]" <JohnH...@online.microsoft.com> wrote in message
news:0M3eTjxrBHA.1364@cpmsftngxa09...

John Hornick [MS]

unread,
Feb 18, 2002, 8:36:48 AM2/18/02
to
Hi,

> I read the paper Q160129 and implemented it myself such that when a job is
> sent to the printer (and for a time after it has printed), I periodically
> (every 20mS) check to see if the printer is in an error state using
> GetPrinter, this continues to return 0. I'm writing an application where
it
> is absolutly critical that print jobs, print as expected, the plan was
that
> any error occuring around the time of doing a print job will result in an
> error stating that there is a possibility the job has not printed. The
> operator would therefore check the printer and re-resend the jobs to
print.
>
> Any advice you could give me on getting a printer's status would be very
> much grately appreciated
>
> I include below my investigating code:

You didn't follow the article. There's actually code in the article - did
you
try it? As the article demonstrates, you need to check both the printer and
job status. Re-read the article and try the code in it.

Thanks,
- John
Microsoft Developer Support
This posting is provided "AS IS" with no warranties, and confers no rights.

Visit http://www.microsoft.com/security for current information on security.

Chris Ward

unread,
Feb 19, 2002, 12:08:30 PM2/19/02
to
"John Hornick [MS]" <JohnH...@online.microsoft.com> wrote in message
news:SvwdxFIuBHA.1988@cpmsftngxa07...


Thanks for the interest John although I have to report that I had tried the
code
from the article, but unfortunatly this doesn't appear to help me. I ran the
following code:

while(true)
{
if (IsPrinterError(hPrinter) == TRUE)
{
MessageBox(NULL, "Printer Is In Error", "", 0);
}
Sleep(20);
}

sent lots of jobs to the printer concerned, turned the printer off in the
middle
of a job, but no error was reported. Then I did exactly the same a few more
times
but with the same result.

Any ideas would be very much appreciated.

Many Thanks


James DeBroeck [MS]

unread,
Feb 19, 2002, 3:54:34 PM2/19/02
to
Hi Chris,

Does this printer's queue in the printers folder show you any error when
you are running the IsPrinterError() loop with the printer turned off?

I suspect that it does not.

As the article points out, the port/language monitor is the one responsible
for detecting A] that an error writting to the printer has occured and B]
reporting that error to the printer queue.

A and B must be true to receive error notifications. The code in Q160129
cannot return any more information than that which is reflected in the
printer's folder. This is because, as the article describes, the operating
system gets all of its information from the port monitor. If the port
monitor doesn't report it, nobody else can get it.

The other possibility is that the status may be set in printers folder but
the code in Q160129 doesn't consider that particular status to be an error.


Sincerely,
James
Microsoft Windows Developer Support


The fine but small print:

Chris Ward

unread,
Feb 20, 2002, 10:19:44 AM2/20/02
to
James,

Many thanks for your response, unfortuanatly the printer's folder reports no
more information than the code included in Q160129.

Is there anyway I can query the port monitor directly?. If this is not
possible, any other ideas which fall short of writing my own port monitor
(I'm not sure how hard that would be since I've been able to find so little
documentation around this topic, even after a week of investigation I'm
still in the dark).

I've also come accross bidispl.h which appears to also perform the task of
retrieving the state of a printer, is this as likely to succeed as the API
calls (currently I'm having trouble finding the dll associated with bidispl,
any ideas?).

Many Thanks

Chris.


Kevin Milch

unread,
Feb 20, 2002, 1:40:33 PM2/20/02
to
Hi James -

I am having exactly the same problem using Windows 98. My printer
status is always 0. Is it the Print Spooler that supplies all that
information or is it the Port Monitor? I don't think the Port Monitor
is going to know whether the printer toner is low. So is the process
like this:

GetPrinter() -> Entry point in Print Spooler (spool32.exe)
Print Spooler -> Calls in to print driver to get status

??

If I remove the paper from my printer, then do the following:

OpenPrinter()
GetPrinter() -> Status returns 0
StartDocPrinter()

loop
WritePrinter()
GetPrinter() -> Status returns 0

EndDocPrinter()

Wait a while, then I get a message from the Printers Folder that I am
out of paper. So the Printers Folder can detect I am out of paper,
but GetPrinter apparently does not. So I just set the Not Selected
timeout for that printer to be 1 second, so I get a quicker message -
which is what I was wanting anyway.

Regards,

Kevin

Kevin Milch

unread,
Feb 20, 2002, 3:04:28 PM2/20/02
to
Chris -

If you have to obtain the printer status before printing you can try
the following if you are using Win95/98/Me :

hf = CreateFile( "\\\\.\\LPT1"
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);


if ( ClearCommError(hf, &dwErr, &stat) )
{
if ( dwErr & CE_DNS )
// Device not selected

if ( dwErr & CE_OOP )
// Out of paper

if ( dwErr & CE_PTO )
// Printer time out
}

***

Then you can use the file handle to write to your printer:

WriteFile( hf, etc... )

Or if you want to use the Print spooler functions, then you can

CloseHandle(hf)

Then use OpenPrinter,WritePrinter,ClosePrinter, etc.

You might have to mess with both File and Spool options to see which
works best for you. I have been messing with both and am leaning
toward using the spool functions if they will allow me to keep the
handle open for a semi-infinite amount of time.

btw - I have written a port monitor and it has nothing to do with this
particular problem.

Regards,

Kevin

James DeBroeck [MS]

unread,
Feb 22, 2002, 9:28:10 PM2/22/02
to
Hi Chris,

If you are using the LocalMon port monitor, then in this case it doesn't
have any additional error information than what you are getting from my
article.

This is because it is a generic port monitor and thus doesn't understand
any error conditions beyond the general ones. It basically writes bytes to
the port in question and waits for it to succeed or return a file I/O
error. If you are curious, check out this port monitor's code in the
Windows DDK.

This port monitor relies on the physical printer at the other end of the
port to set error bits on the parallel port. Most likely, the printer you
are using is not doing this if you never get any error information.

If this is the case, I don't think writting your own port monitor would
even help. The error state isn't being advertised by the printer.

If the printer in question is bidi capable, then its feasable that you
would write a language monitor to "query" the printer for its current
state. This would solve the issue of the printer not setting hardware
errors. More information on language monitors can be found in the DDK under
Print Monitors.

bidispl.h is for use with COM interfaces introduced with Windows XP. You
therefore will not "find" any DLL's associated with it. The registered COM
server is part of XP. This functionality presumes that the printer is BiDi
and that a full Print Monitor implementing a language monitor is installed.
Neither of which appears to be true for your case so it wouldn't help
anyway.

James DeBroeck [MS]

unread,
Feb 22, 2002, 9:31:00 PM2/22/02
to
Kevin,

Q160129 describes the error reporting process. Yes, the port monitor is the
one reporting the error.

The article describes why it is important to check both the printer queue
and the jobs in the queue for errors.

0 new messages