Received Print Job Python Received Print Job Python windows windows

Received Print Job Python


Here's an idea that worked on my computer (Windows 8). It's hardly fully fledged code, but it might get you going. You need to utilise the functions FindFirstPrinterChangeNotification and FindNextPrinterChangeNotification These are contained within winspool.drv on the client side (irritatingly you can find them documented as being in spoolSS.dll but this is server side - this diagram can clarify).

The list of events that can be listened for (and, importantly, their flag settings) are available from MSDN here. Initially I thought you wanted PRINTER_CHANGE_ADD_JOB (0x00000100), but I think you may actually want PRINTER_CHANGE_WRITE_JOB (0x00000800). This doesn't trigger as soon as the job starts spooling, but unfortunately it does seem to be triggered multiple times in the example where you send one document to a network printer.

Unfortunately, these APIs aren't exposed in the win32print library. I think, therefore you have to dive into ctypes. Here I haven't registered a callback as such, rather I listen for the notification and when triggered I call the function and start listening again in an infinite loop. The process is stalled while listening. If you need conventional callback functionality, you could either run this script in its own thread, or maybe this answer will not suit your needs.

Note - this simply listens for the print job being requested and then calls a function. If you want to extract information about the job being triggered, the code will become horrendous. Further note - it will trigger for a print job that is started and subsequently cancelled, but I imagine that's fine.

from ctypes import *from ctypes.wintypes import HANDLE, LPSTRdef add_job_callback():    print('A job has just been sent to the printer this script is monitoring')spl = windll.LoadLibrary('winspool.drv')printer_name = 'KONICA MINOLTA PS Color Laser Class Driver'# Put the name of your printer here - can be networked or any installed on your computer.  Alternatively, set it to None to use the local printer server#printer_name = NonehPrinter = HANDLE()if printer_name:    spl.OpenPrinterA(c_char_p(printer_name), byref(hPrinter),None)else:    spl.OpenPrinterA(None, byref(hPrinter),None)print(hPrinter)hjob = spl.FindFirstPrinterChangeNotification(hPrinter,0x00000100,0, None)# 0x00000100 is a flags setting to set watch for only PRINTER_CHANGE_ADD_JOBwhile True:    windll.kernel32.WaitForSingleObject(hjob,-1)    #When this function returns, the change that you're monitoring for has been observed, trigger the function    add_job_callback()    spl.FindNextPrinterChangeNotification(hjob, None, None, None)

Note there are some small differences between Python 2.7 and Python 3 here - e.g. the initialisation of the c_char_p ctype from a string. I've presented the simplest version I could here - it works in 2.7.


Postscript

I did all the heavy lifting and then found this answer, that is something of a duplicate. It has rather nicer code that handles unicode printer names and the like, but only looks at the default local print server.