You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

远程打印机主机重启后FindFirstPrinterChangeNotification不再触发

远程打印机主机重启后打印作业通知失效问题

我开发的Windows工作站软件负责检测和管理打印作业,打印机通过Windows共享部署在远程主机上。目前存在的问题是:远程打印机主机重启后,FindFirstPrinterChangeNotification函数不再触发,无法检测新的打印作业,必须重启工作站或软件才能恢复正常。

相关代码

from ctypes import byref, PRINTER_NOTIFY_OPTIONS, PPRINTER_NOTIFY_INFO_GC, PRINTER_NOTIFY_OPTIONS_TYPE, JOB_NOTIFY_TYPE, wintypes
import win32con, win32event, win32gui, win32print, win32ui
winspool = ctypes.WinDLL('winspool.drv', use_last_error=True)

JOB_NOTIFY_FIELD_PRINTER_NAME        = 0x00
JOB_NOTIFY_FIELD_MACHINE_NAME        = 0x01
JOB_NOTIFY_FIELD_PORT_NAME           = 0x02
JOB_NOTIFY_FIELD_USER_NAME           = 0x03
JOB_NOTIFY_FIELD_NOTIFY_NAME         = 0x04
JOB_NOTIFY_FIELD_DATATYPE            = 0x05
JOB_NOTIFY_FIELD_PRINT_PROCESSOR     = 0x06
JOB_NOTIFY_FIELD_PARAMETERS          = 0x07
JOB_NOTIFY_FIELD_DRIVER_NAME         = 0x08
JOB_NOTIFY_FIELD_DEVMODE             = 0x09
JOB_NOTIFY_FIELD_STATUS              = 0x0A
JOB_NOTIFY_FIELD_STATUS_STRING       = 0x0B
JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR = 0x0C # not supported
JOB_NOTIFY_FIELD_DOCUMENT            = 0x0D
JOB_NOTIFY_FIELD_PRIORITY            = 0x0E
JOB_NOTIFY_FIELD_POSITION            = 0x0F
JOB_NOTIFY_FIELD_SUBMITTED           = 0x10
JOB_NOTIFY_FIELD_START_TIME          = 0x11
JOB_NOTIFY_FIELD_UNTIL_TIME          = 0x12
JOB_NOTIFY_FIELD_TIME                = 0x13
JOB_NOTIFY_FIELD_TOTAL_PAGES         = 0x14
JOB_NOTIFY_FIELD_PAGES_PRINTED       = 0x15
JOB_NOTIFY_FIELD_TOTAL_BYTES         = 0x16
JOB_NOTIFY_FIELD_BYTES_PRINTED       = 0x17
JOB_NOTIFY_FIELD_REMOTE_JOB_ID       = 0x18


PRINTER_CHANGE_ADD_JOB = 0x00000100
DEFAULT_FIELDS = (
    JOB_NOTIFY_FIELD_PRINTER_NAME,
    JOB_NOTIFY_FIELD_STATUS,
    JOB_NOTIFY_FIELD_DOCUMENT,
    JOB_NOTIFY_FIELD_TOTAL_PAGES,
    JOB_NOTIFY_FIELD_DEVMODE)

def pause_and_get_print_job_info(self, printer_name: str=None, timeout: float=-1):
    EVENEMENT_IMPRIMANTE = win32event.WAIT_OBJECT_0
    EVENEMENT_DECONNEXION = win32event.WAIT_OBJECT_0 + 1
    RESULTAT_VIDE = { "print_job_id": -1 }
    RESULTAT_DECONNEXION = { "print_job_id": -9999 }

    if (timeout != -1):
        timeout = int(timeout * 1000)

    hPrinter = wintypes.HANDLE()
    change_detected = wintypes.DWORD()
    fields = (wintypes.WORD * len(DEFAULT_FIELDS))(*DEFAULT_FIELDS)
    opt = PRINTER_NOTIFY_OPTIONS(pTypes=PRINTER_NOTIFY_OPTIONS_TYPE(Type=JOB_NOTIFY_TYPE, pFields=fields))
    pinfo = PPRINTER_NOTIFY_INFO_GC() # note: GC subclass
    result = RESULTAT_VIDE
    winspool.OpenPrinterW(printer_name, byref(hPrinter), None)

    try:
        hChange = winspool.FindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_ADD_JOB, 0, byref(opt))

        try:
            # The result will be WAIT_OBJECT_0 if the printer triggered the event, WAIT_OBJECT_0 + 1 if the event comes from session closure.
            event_result = win32event.WaitForMultipleObjects([hChange, self._shutdown_event], False, win32event.INFINITE)

            ###### The thread never reaches this point. WaitForMultipleObjects is stuck waiting, until a shutdown / disconnect occurs. #####
            
            # This means there was an error.
            if event_result not in (EVENEMENT_IMPRIMANTE, EVENEMENT_DECONNEXION):
                return RESULTAT_VIDE
            # The Shutdown / Disconnect event was triggered.
            elif event_result == EVENEMENT_DECONNEXION:
                return RESULTAT_DECONNEXION

            winspool.FindNextPrinterChangeNotification(hChange, byref(change_detected), None, byref(pinfo))
            
            # [...] The rest of the Windows print job processing follows.

已尝试的解决措施

  • 在工作站防火墙添加文件和打印共享例外
  • 改用WaitForSingleObject配合FindFirstPrinterChangeNotification

推测原因

远程主机重启后,打印机句柄发生变化,原句柄绑定的通知事件无法接收新打印作业,但不知如何解决该问题。


内容的提问来源于stack exchange,提问作者InLibrolivier

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 04:57:07