[RESOLVED] How to determine if a printer is connected and available
I wish to determine whether a particular named USB printer is connected and available and to use this fact as a conditional element of my program.
Using the control panel in windows XP (looking at printers and faxes) the status of each device for which a driver is loaded is displayed as OFFLINE or READY). My wish is to access this status information, or similar, through VB6 program code.
I have spent several hours looking through previous Forum posts and other Googled sources but none seems to offer what would seem to be a simple solution to what is surely a simple question : Is printer "its name" OFFLINE or READY?
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Re: How to determine if a printer is connected and available
Thank you Bonnie West.
I had found that thread/info and have been trying for hours to make it work. I simply can not.
Can you / anyone please supply a sample of code which, given a printer device name (eg. "Epson 2400") returns a value which indicates whether it is on/connected/available, or not?
This seems such a simple request, but I am finding the solution very difficult. Be assured that I never post questions to the Forum without first having done my very best to find answers.
Re: How to determine if a printer is connected and available
Thank you Gibra,
I downloaded and ran the VB program you suggested in that link. It looks to be a VERY complicated and comprehensive piece of software.
However, it does not work. It correctly lists all of my connected printers, but it declares them all as 'ready'. Then if I completely disconnect a printer and re-run the program, it still declares that printer as 'ready'. Have you encountered this problem?
Re: How to determine if a printer is connected and available
Have you tested the codes you've collected on another computer using the same or different printer(s)?
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Re: How to determine if a printer is connected and available
Bonnie West,
No, am still trying to achieve function on Win XP computer.
There is no point in trying the code on any other machine because when I run it I get numerous compile errors and it just halts/fails.
The code is (for me at least) very complicated and there is not a comprehensive explanation as to how to use it. That is why I asked if anyone has a working piece of code which I can understand and adapt.
Why should it be so (apparently) difficult to write a piece of code which checks whether printer "printer name" is connected and available?
Re: How to determine if a printer is connected and available
The only way I know of to check whether a printer is ready or not, is to send something to it. If the printer is not able to accept the job, it stays in the printer Spool with an error and an Icon pops up in the system tray. Correct the problem with the printer and tell the Spooler to send it again. To verify if a printer driver is functional, simply right button click on the driver in the "Printers" window, click on properties, and send a test page to the printer.
Last edited by Bonnie West; Sep 12th, 2013 at 06:22 AM.
Reason: Added Enum & Type
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Re: How to determine if a printer is connected and available
couttsi : see my initial post #1 above. In Windows the status of printers and faxes (OFFLINE or READY) can be read at the Printers and Faxes section of the control panel. My wish is "simply" to be able to obtain this selfsame information for a named printer in a VB6 program. There is no need to send anything to the printer to print before the windows control panel reports the status of the printers.
Bonnie West : Thank you for the code. With a tweek or two I have got it running without generating any errors, but I can not seem to get it to read the PRINTER_INFO_6 status messages. The line
IsPrinterReady = PRINTER_INFO_6 = 0&
Does not seem to return correct values. The link you kindly provided to that status definitions/list shows C++ syntax but not that for VB6. Your code appears to use a hexadecimal number to specify the status element wanted - but at that link those elements are listed as words eg. PRINTER_STATUS_OFFLINE.
I have tried lots of things without success. Could you please suggest the correct code to use in the above line?
Re: How to determine if a printer is connected and available
@ camoore
When you step through that code, what is the value of PRINTER_INFO_6? I'm assuming that a value of 0 means that the printer is "ready", as suggested in the Getting the status of the selected printer from Visual Basic article:
Code:
Public Enum Printer_Status
PRINTER_STATUS_READY = &H0
There isn't actually a constant like that defined anywhere in the Windows header files. Like the author of that article, we're both assuming that if no other bit (the PRINTER_INFO_6's dwStatus member is, in fact, a bit field) is set, then it probably means that the printer is ready. You may want to see which bits are really set when you call that function.
EDIT
BTW, the MSDN doc describes the meaning of each constant whose values are enumerated in the Merrion article. The ampersand (&) after the numeric literals in my code forces VB6 to treat them as Longs instead of Integers so that no run time conversion needs to take place.
Last edited by Bonnie West; Sep 12th, 2013 at 06:02 AM.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Re: How to determine if a printer is connected and available
Bonnie West :
I wrote a loop which ran this line :
IsPrinterReady = PRINTER_INFO_6 = N
using values of N from 0 to 1000+
When N = 0 IsPrinterReady shows as TRUE. For all other values of N it shows as FALSE. Moreover it does this whether or not the printer is connected to the computer.
I am baffled. This is a new field of VB6 for me, so am probably missing something very simple.
Re: How to determine if a printer is connected and available
Could you run the code in post #9 again? Please set a breakpoint at the start of the function and step through the code (press F8). When you reach the IsPrinterReady = PI6.dwStatus = 0& line, what is the value of PI6.dwStatus?
EDIT
If it's possible, could you compile a small test program using the code in post #9 and test any printer using a different computer. We want to make sure that your development PC isn't at fault here.
Last edited by Bonnie West; Sep 12th, 2013 at 07:37 AM.
On Local Error Resume Next: If Not Empty Is Nothing Then Do While Null: ReDim i(True To False) As Currency: Loop: Else Debug.Assert CCur(CLng(CInt(CBool(False Imp True Xor False Eqv True)))): Stop: On Local Error GoTo 0
Re: How to determine if a printer is connected and available
[I believe] CommonDialog will display all printers currently configured on your system regardless of the status - the problem here is that printer maybe disconnected.
Best example to visualize what camoore is trying to accomplish could be network map where you can see all devices with their respective statuses.
Re: How to determine if a printer is connected and available
[I believe] CommonDialog will display all printers currently configured on your system regardless of the status and that it will report the status of the selected one, unfortunately the status reported is not reliable.
Re: How to determine if a printer is connected and available
Thank you jcis, Rhino Bull and Magic Ink for your posts.
JCIS / RHINO BULL / Magic Ink : I tried the common dialog method. This does indeed show all printers of which drivers have been loaded. When I perform a MOUSEOVER, I get something like a VB Tooltip which tells me the status of each printer. Hovever a. (as Magic Ink mentioned) there can be errors [it showed a remote shared printer on another machine as available - yet that other machine was turned off] and b. there does not appear to be a way of importing in a fashion which VB6 can understand the actual reported status of each specified printer.
Hence the original problem remains unsolved for me - how can VB6 ascertain the current availability/connection status of a specified printer?
The modified code suggested by Bonnie West at #9 above seems almost to be working - but not quite yet. I am hoping that Bonnie West may have a further suggestion - but welcome any and all alternatives.
When I post questions to this excellent Forum I always spend a long time beforehand trying to work out answers and/or trying to find solutions elsewhere on this and other Fora. At least on this occasion there has not been a totally obvious and simple answer to my query which I have missed.
Re: How to determine if a printer is connected and available
It could be there is a reliable way of reliably determining the status of a printer but if there was it is likely that the common dialog would use it; not all things are possible...
Re: How to determine if a printer is connected and available
I hate to be defeated by these problems.
After a lot of experimentation and work, I believe that I may have solved the problem of "how to determine if a (named) printer is connected and available?".
I am attaching for your info. my development/demonstration program. It is commented, and so should be quite easy to understand.
The code is contained in a module. Only the simplest of instructions is required to run the module and it comes back with a yes/no answer. (see Form1 Command 1)
The code is heavily based on the Merrion article mentioned by Bonnie West at post #2 of this thread, but also upon Bonnie's subsequent suggestions.
What I found is that using PRINTER_INFO_2 the value of Buffer(13) - the printer attributes value - changes between two specific values depending upon whether the printer is connected and running or not. Great, but I then found that while the same holds good for another type of printer, the two specific values between which Buffer(13) changes are different. So it was not sufficient just to trap those values. They vary from printer to printer.
I guessed that, as Bonnie mentioned, this attributes value is a bit field. Therefore I converted the decimal value of Buffer(13) to binary and found that the third bit changed from a 1 to a 0 with both printers (although the other bits set were different). So my program traps that third bit of attributes.
I have only two printers and this routine works with both of them, but would very much like to hear if it works for others.
Am most grateful for all assistance thus far.
camoore
Wales, UK
EDIT : As a result of this thread the program has been improved and expanded. Please read through the thread, and then use the version "Test Printer Status (1)" attached at post #32 below. 18/Sept/13
Last edited by camoore; Sep 18th, 2013 at 04:03 AM.
Re: How to determine if a printer is connected and available
HI, and thanks dilettante
By "third bit" what I mean is this : The decimal value of Buffer(13) is read. This is converted into a 13 bit binary number. The third bit to which I refer is the third most significant (value 1024).
I am not at all sure how this relates to the attribute values which you list. While I have made some progress in this, I have not yet comprehensively understood or managed to extract (using the Merrion based program) these detailed status quantities.
The only thing I can say is that, based on just two different printers I have and running under Win XP, the program is doing what I wish. If the printer of which the status is wanted is specified at Form1.Command 1 (it must be the exact windows name, as you get with control panel printers & faxes or with the common dialogue control) then my program reports whether it is connected and powered up.
Plug in the specified printer and it says "READY". un-plug it, switch its mains off or plug in a different printer and it says NOT READY. That was my simplistic aim.
When the test program is run, a list box shows the values of the first 20 buffers. If you have a printer (or more than one) it would be interesting to know what values you see for Buffer(13) with it connected and not connected.
As you are aware, I am by NO means an expert. Just trying to get an idea to work.
Regards,
camoore
Wales, UK
Last edited by camoore; Sep 15th, 2013 at 06:10 AM.
Re: How to determine if a printer is connected and available
Thanks you Si,
Without a printer the program can still be tested, assuming that you have a printer driver installed. If my idea is correct the program should report that the printer is NOT READY. It would still be interesting to know the decimal value of Buffer(13) then - because it will probably be another printer-specific not-connected value. To do this you will first need to write the appropriate Windows printer name into Form1.Command1.
Re: How to determine if a printer is connected and available
Er, that would be bit 9, PRINTER_ATTRIBUTE_WORK_OFFLINE as stated above. Bits are counted from 0 at the low-order position.
If this gives you what you need that's great, but don't call it "not ready" because that isn't what not ready means. It is perfectly "ready" for printing but printouts will be spooled until it comes back online.
A printer can be online but not ready, as in the case where somebody has pressed a printer button to make it not ready to change paper, etc.
Re: How to determine if a printer is connected and available
I've got two drivers installed (XPS Writer, and Fax). It returned 1 for XPS (which is expected), and 0 for Fax (which isn't surprising, I've never attempted to use it).
Note that while looking at your code I noticed a few things that are less than ideal, the most important being unnecessary use of goto which makes the code much harder to read.
An example is this section:
Code:
Line16:
If N < M Then
BUF13BINARY = BUF13BINARY & "0"
GoTo Line20
End If
BUF13BINARY = BUF13BINARY & "1"
N = (N - M)
Line20:
If M = 1 Then GoTo Line10
M = M / 2
GoTo Line16
Line10:
...which is equivalent to this version that doesn't involve finding the labels:
Code:
Do
If N < M Then
BUF13BINARY = BUF13BINARY & "0"
Else
BUF13BINARY = BUF13BINARY & "1"
N = (N - M)
End If
If M = 1 Then Exit Do
M = M / 2
Loop
Re: How to determine if a printer is connected and available
Some bad news I'm afraid... your code to convert to binary (part of which I quoted above) assumes the highest possible bit value is 4196, but the value for my Fax driver is 16448 (which should be 100 0000 0100 0000, but shows as all 1's).
Switching it to bit-masking shows 1 for both my printer drivers:
Code:
If (BUFFER(13) And &H400) = &H400 Then
Form1.PRINTERREADY = 0
Else
Form1.PRINTERREADY = 1
End If
Re: How to determine if a printer is connected and available
Your routine lies to me on a Win 7 machine when I ask it for the status of an HP 6127 networked printer (using an HP 990C driver as recommended), it reports "Ready" when 1) the printer is powered down and or 2) the printer is switched on but the network is disabled. The status reported in the Common dialog/ Devices and Printers dialog usually gets it right in the end but only after a time lag.
On an XP machine on the same network I get the same results for the networked HP 6127 but the status of an HP OfficeJet 6310 connected directly to the machine via a USB lead is reported correctly after a short time lag.
Re: How to determine if a printer is connected and available
Dilletante and Si : comments noted thank you.
The largest value I had seen for Buffer(13) was 3648 with my Epson printer unplugged, so I wrote the program to deal with a 13 bit binary number (max. value therefore 8191). However looking at dilletante's attributes list in his post above I realised that there appear to be 16 attribute bits. If all were to be set, the buffer value would be 65535. Any buffer value greater than 4196 will not work correctly with my code.
So the code is modified to deal with a Buffer value of up to 65536, which is a 17 bit binary number. The bit which I seek is then the 7th from the left or 11th from the right whichever way one prefers to look at it.
Below is the modified section of module 1 code, which also includes Si's better Do Loop suggestion.
camoore
Wales,UK
Code:
'Now to convert the decimal value of Buffer(13) into a binary
'bit pattern and store this in string variable BUF13BINARY
Line15: 'and show Buffer(13) value as a binary bit pattern at Form1.Label1
N = BUFFER(13)
BUF13BINARY = ""
M = 65536
Do
If N < M Then
BUF13BINARY = BUF13BINARY & "0"
Else
BUF13BINARY = BUF13BINARY & "1"
N = (N - M)
End If
If Round(M, 0) = 1 Then Exit Do
M = M / 2
Loop
Line10: 'BUF13BINARY is now the 17 bit binary value of Buffer(13)
'eg. 00000011000100010
Form1.Label1.Caption = BUF13BINARY 'display this binary value at form 1
' For info, these are the listed meanings of the 16 Attribute bits
' PRINTER_ATTRIBUTE_QUEUED 0x00000001 Decimal value = 1 (LSB)
' PRINTER_ATTRIBUTE_DIRECT 0x00000002 Decimal value = 2
' PRINTER_ATTRIBUTE_DEFAULT 0x00000004 Decimal value = 4
' PRINTER_ATTRIBUTE_SHARED 0x00000008 Decimal value = 8
' PRINTER_ATTRIBUTE_NETWORK 0x00000010 Decimal value = 16
' PRINTER_ATTRIBUTE_HIDDEN 0x00000020 Decimal value = 32
' PRINTER_ATTRIBUTE_LOCAL 0x00000040 Decimal value = 64
' PRINTER_ATTRIBUTE_ENABLE_DEVQ 0x00000080 Decimal value = 128
' PRINTER_ATTRIBUTE_KEEPPRINTEDJOBS 0x00000100 Decimal value = 256
' PRINTER_ATTRIBUTE_DO_COMPLETE_FIRST 0x00000200 Decimal value = 512
' PRINTER_ATTRIBUTE_WORK_OFFLINE 0x00000400 Decimal value = 1024
' PRINTER_ATTRIBUTE_ENABLE_BIDI 0x00000800 Decimal value = 2048
' PRINTER_ATTRIBUTE_RAW_ONLY 0x00001000 Decimal value = 4096
' PRINTER_ATTRIBUTE_PUBLISHED 0x00002000 Decimal value = 8192
' PRINTER_ATTRIBUTE_FAX 0x00004000 Decimal value = 16384
' PRINTER_ATTRIBUTE_TS 0x00008000 Decimal value = 32768 (MSB)
'we now examine the value of the seventh binary bit in BUF13BINARY (1024)
'this has meaning WORK OFFLINE
If Mid$(BUF13BINARY, 7, 1) = "0" Then Form1.PRINTERREADY = 1
If Mid$(BUF13BINARY, 7, 1) = "1" Then Form1.PRINTERREADY = 0
EDIT : Forgot to mention a. Dim variables M and N as Long, not Integer and b. At Form1 Label1 reduce font size to 12 so as to show all 17 bits in the box.
FURTHER EDIT : Corrected a code error. Initial value of M for the binary conversion should be 65536
Last edited by camoore; Sep 16th, 2013 at 12:07 PM.
Reason: Omission
Re: How to determine if a printer is connected and available
Si / Magic Ink
For some reason your last two posts did not show on my machine until I sent post #30 just now.
Si : I had anticipated a problem if the buffer value was greater than 8191 and that is corrected in my #30 code change. You got a value of 16448. In 17 bit binary I make that 00100000001000000 as you posted (I used the amended program to calculate this). In this number, the seventh bit from left is a 0, which should indicate that device was READY, ie. not offline.
This seems to be a problem with the program.
Magic Ink : I have not yet tried the code on a Win 7 machine, so can not suggest whether that is a factor. On my XP setup the common dialogue shows a networked printer as READY when it is not even powered up! I have yet to try my status program on this networked printer. The program has only been written for a printer which is directly connected to a computer. It may be that it will not work with network devices - that is tbd. At least it works OK for your HP 6310 on direct connection.
About the time lag, I have also noticed that. I find that when a printer is disconnected the program still shows it as READY for about 3 seconds. The same happens when I open Printers and Faxes in the Control Panel - it takes about 3 seconds for the machine to update status from READY to OFFLINE or vice versa.
camoore
Wales, UK
EDIT : Response to Si amended due to my error with the binary conversion. This also corrected by edit to post #30 above. MUST take more care!
Last edited by camoore; Sep 16th, 2013 at 12:16 PM.
Re: How to determine if a printer is connected and available
I believe that I should shortly mark this thread as resolved, with thanks to all who have contributed.
Attached is the developed version of the program (Test Printer Status (1)). Additional values are defined for PRINTERREADY in an attempt to deal with Networked printers and the Fax (as mentioned by Si).
My original aim was effectively to enable VB6 to import/enumerate the READY/OFFLINE status information for a named printer as is displayed at the Windows Control Panel Printers and Faxes page. That has, for my needs, been achieved. I was only concerned to check whether a named printer was connected directly to the computer, and whether it was switched on. Based upon the two printers I have and upon the report from Magic Ink about their HP 6310, the program worked.
I further believe (but can not say with confidence) the following :
1. So-called "virtual printers" if installed always show status as READY.
2. Shared printers (on another computer networked to this computer) if installed always show READY status, even if that other computer is switched off. The Windows Control Panel does the same thing for me here.
3. Printers connected via a Network (or server etc.) show READY status, whether available or not. I have added a PRINTERREADY value for a networked printer, but can not test this here.(perhaps Magic Ink can do this?)
4. There remains a query concerning the Fax result which Si reported. Maybe his Fax was installed as a virtual printer. I did note that the Buffer(13) value which Si got had the Fax bit set to "1", so have added a special value for PRINTERREADY to indicate this.
5. With regard to 2. and 3., it seems that only a computer actually directly connected to a printer can properly determine its status. Hence in case 2 if a remote shared printer is specified the local machine assumes that it is available - which seems to be what the Control Panel does too.
Without doubt the program is capable of improvement and/or further addition based upon parsing out and acting upon the various bits of the attribute field - which is being done in the last few lines of code in Module1.
Re: How to determine if a printer is connected and available
I am about to mark this thread as Resolved, with thanks to all who have contributed.
Concerning what Si reported about his Fax showing as Ready when not even connected, I have seen the same thing on another machine which has a Fax facility installed. (The Printers and Faxes page of the Control Panel also says it is Ready). This reinforces my thought that Faxes get installed as virtual printers and as such are always reported as being Ready. The final version of the development program attached above returns a special value of PRINTERREADY if the fax bit is set in the attributes bitfield.
Re: How to determine if a printer is connected and available
When the status is "Network Printer", is there a way to know whether the printer is "Ready" or "Offline"? My quick test seems to give "Network Printer" result, regardless of whether the printer is turned ON or OFF.
Re: [RESOLVED] How to determine if a printer is connected and available
this is a really old thread, but see post 32 remarks 2 and 3
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: [RESOLVED] How to determine if a printer is connected and available
Originally Posted by westconn1
this is a really old thread, but see post 32 remarks 2 and 3
Westconn1, thanks for replying...
Yes, it's an older thread, but addresses exactly what i am looking to do. maybe i should start a new thread?
From post 32, it seems that there is not an ability to read "READY" for a network printer (or shared printers on another computer networked to this computer)? Per comment 5, "if a remote shared printer is specified the local machine assumes that it is available".
i'm wondering if there is a programmatic 'test' that could be done, to determine if a "shared printer" is really available or not?
i do my best to test code works before i post it, but sometimes am unable to do so for some reason, and usually say so if this is the case. Note code snippets posted are just that and do not include error handling that is required in real world applications, but avoid On Error Resume Next
dim all variables as required as often i have done so elsewhere in my code but only posted the relevant part
come back and mark your original post as resolved if your problem is fixed
pete
Re: [RESOLVED] How to determine if a printer is connected and available
Yes it is an old thread, but still very useful :-)
I have just tried the program with latest release of Windows 10 (March 2022) and it does correctly show a Canon TS9100 printer is ready (when it is ready to print) and Not ready (when switched off).
This is not actually what I need to do, but the thread has given me some ideas of what to try next :-)