简体   繁体   English

收到打印作业Python

[英]Received Print Job Python

I have successfully managed to trigger a callback when a print job is initially requested on the local machine during spooling. 在后台打印期间最初在本地计算机上请求打印作业时,我已经成功设法触发了回调。 However is there anyway with win32print or something similar that may allow me to handle the event in which a print job is transferred to a print server or USB printer? 但是,无论如何有win32print或类似的东西可以让我处理将打印作业转移到打印服务器或USB打印机的事件?

################################################################################
# Imports ######################################################################
################################################################################

from os.path import *
from printer import *
from watcher import *
from statvar import *

################################################################################
# Event Callback ###############################################################
################################################################################

def callback(code, event):

    num = splitext(event)[0]
    ext = splitext(event)[1]

    if code == 1 and ext == '.SPL':
        main(num.lstrip('0'))

################################################################################
# wx Event Handler #############################################################
################################################################################

def handling(*args):

    wx.CallAfter(callback, *args)

################################################################################
# Create Listener ##############################################################
################################################################################

# listens to the spool directory for files

watch = Watcher(SPOOL_DIRECTORY, handling)

# set the appropriate flags for a listener

watch.flags = FILE_NOTIFY_CHANGE_FILE_NAME

################################################################################
# Start Listener ###############################################################
################################################################################

watch.start()

################################################################################
# Start wx App #################################################################
################################################################################

app = wx.App()
wx.Frame(None)
app.MainLoop()

################################################################################
################################################################################
################################################################################

Here's an idea that worked on my computer (Windows 8). 这是在我的计算机(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). 您需要利用功能FindFirstPrinterChangeNotificationFindNextPrinterChangeNotification这些功能包含在客户端的winspool.drvspoolSS.dll是,您可以找到它们记录在spoolSS.dll但这是服务器端的, 此图可以阐明)。

The list of events that can be listened for (and, importantly, their flag settings) are available from MSDN here . 可从MSDN此处获得可以监听的事件列表(重要的是,它们的标志设置)。 Initially I thought you wanted PRINTER_CHANGE_ADD_JOB ( 0x00000100 ), but I think you may actually want PRINTER_CHANGE_WRITE_JOB ( 0x00000800 ). 最初,我认为您需要PRINTER_CHANGE_ADD_JOB0x00000100 ),但我认为您实际上可能需要PRINTER_CHANGE_WRITE_JOB0x00000800 )。 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. 不幸的是,这些API并未在win32print库中公开。 I think, therefore you have to dive into ctypes . 我认为,因此您必须深入研究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, LPSTR

def 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 = None

hPrinter = 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_JOB
while 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 - eg the initialisation of the c_char_p ctype from a string. 请注意,此处的Python 2.7和Python 3之间有一些细微的差异-例如,从字符串初始化c_char_p ctype I've presented the simplest version I could here - it works in 2.7. 我已经介绍了我可以在这里找到的最简单的版本-它可以在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. 它具有处理unicode打印机名称之类的更好的代码,但仅查看默认的本地打印服务器。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM