Saturday, January 24, 2009

Printer status monitoring II

Since I developed the small class and application for monitoring the status of printers and jobs I've set upon improving it.  Specifically I was aiming to improve the mechanism it uses to track changes to the printers and print jobs.

There are really two options for this type of processing, you either poll the printers and queues on a regular basis or you make use of some type of notification process which will wake up your processing when an event occurs.

The first incarnation of the printer monitor test application relied on simple polling since I wasn't actually developing that part of the functionality - I was interested in getting the status information for the printers and jobs.

But, having the ability to handle the capture of printer and job state changes looks useful and I set about improving on the simple polling technique.

Windows implements a printer event notification process through the FindFirstPrinterChangeNotification API and its companion API's FindNextPrinterChangeNotification and FindClosePrinterChangeNotifcation.

Prior to calling FindFirst... you need to set up two structures, PRINTER_NOTIFY_OPTIONS_TYPE and PRINTER_NOTIFY_OPTIONS, which state the type of event and information you're interested in.  You also need an open handle for the printer being monitored.

FindFirst... returns a handle which can be used with the Windows wait functions (WaitForSingleObject etc.) which gives you your basic event monitoring process.

With the waitable handle you call the chosen wait API.  On return, and if the event fired, you can call FindNext... to get the event information allowing you to check printer and job status.  Then you're back to the wait function until the next event fires.

Once you're done, a call to FindClose... releases the resources associated with the wait.

Once contained in their own thread with some enable/disable processing you have a very effective and efficient print monitoring capability which isn't going to interfere with the UI threads.

Once these changes were in, and the rudimentary polling code removed, the monitoring application functioned just as before but with a reduction in system resource usage. It also has simpler access to a range of printer and job related status information which can be exposed through the component interface.

Saturday, January 10, 2009

Printer status monitoring

One of the features I want my component to be able to support is the ability for applications to use it to monitor the status of printers and print jobs.  The easiest way to work out how to do this was to write a small application which gathered and displayed the required information. 

It turned out to be a fairly enjoyable little bit of work which provided a print monitoring class ready for inclusion in my component.

Obtaining printer status, for example detecting out of paper conditions, turned out to be trickier than just asking the printer how it's doing.

Printer status under Windows isn't really a regularly updated and accurate property on the printer itself and can't be reliably obtained by just querying the printer information.

The status of the printer is updated and made available when jobs are actively spooling and printing.

The solution was to iterate over the available printers, using the EnumPrinters API, and for each printer returned look at the information for queued jobs using the EnumJobs API.

Then it was just a case of inspecting information from both the printer (using the PRINTER_INFO_2 structure) and the jobs (using the JOB_INFO_2 structure).  Both of these structures contain status information but I found that the jobs reported more accurately.

The small test application I developed to work through the solution has turned out to be a handy little thing.  When started, it just sits quietly in the corner reporting how the printers it can see, including network attached printers, are doing and how many jobs are in each printer's queue.  So handy in fact that I may just add a little help file and throw it up on the website as a free user downloadable utility application.

Website - done.

A positive start to the New Year!

Actually the new site was live in December but I didn't manage to post an updated blog entry.

I've looked at it for so long that it's looking a little old to me already!

But I did get round to finishing all the little tweaks and I published the site, so I've removed the one big excuse that was keeping me away from developing.

New website is here for those of an inquisitive nature.