What are the events that occur in a system before a document is successfully printed?

[GitHub]: ActiveState/code - (master) code/recipes/Python/305690_Enumerate_printer_job/recipe-305690.py (that raises ctypes.ArgumentError in your case) is ancient, some parts of it only worked by luck, and some of them never worked (as the flow didn't reach them).
I submitted [GitHub]: ActiveState/code - Fixes and updates which addresses the major problems (there are some left, but the code is working).

Starting from that, I tried to tailor it for this question, and address the items (partially at least). Since the question is tagged for [GitHub]: mhammond/pywin32 - pywin32, I used it in order to have (much) shorter (and Python friendlier) code.

code00.py:

#!/usr/bin/env python import sys import time import win32con as wcon import win32print as wprn from pprint import pprint as pp JOB_INFO_RAW_KEYS_DICT = { # Can comment uninteresting ones "JobId": "Id", "Position": "Index", "pPrinterName": "Printer", "pUserName": "User", "pDocument": "Document", "TotalPages": "Pages", "Submitted": "Created", } def generate_constant_strings(header, mod=None): header_len = len(header) ret = {} for k, v in (globals() if mod is None else mod.__dict__).items(): if k.startswith(header): ret[v] = k[header_len:].capitalize() return ret JOBSTATUS_DICT = generate_constant_strings("JOB_STATUS_", mod=wcon) DMCOLOR_DICT = generate_constant_strings("DMCOLOR_", mod=wcon) DMPAPER_DICT = generate_constant_strings("DMPAPER_", mod=wcon) def printer_jobs(name, level=2): p = wprn.OpenPrinter(wprn.GetDefaultPrinter() if name is None else name, None) jobs = wprn.EnumJobs(p, 0, -1, level) wprn.ClosePrinter(p) return jobs def job_data(job, raw_keys_dict=JOB_INFO_RAW_KEYS_DICT): ret = {} for k, v in job.items(): if k in raw_keys_dict: ret[raw_keys_dict[k]] = v ret["Format"] = DMPAPER_DICT.get(job["pDevMode"].PaperSize) ret["Color"] = DMCOLOR_DICT.get(job["pDevMode"].Color) ret["Status"] = JOBSTATUS_DICT.get(job["Status"]) return ret def main(*argv): printer_name = None interval = 3 while 1: try: jobs = printer_jobs(printer_name) for job in jobs: data = job_data(job) pp(data, indent=2, sort_dicts=0) time.sleep(interval) except KeyboardInterrupt: break if __name__ == "__main__": print("Python {:s} {:03d}bit on {:s}\n".format(" ".join(elem.strip() for elem in sys.version.split("\n")), 64 if sys.maxsize > 0x100000000 else 32, sys.platform)) rc = main(*sys.argv[1:]) print("\nDone.") sys.exit(rc)

Output:

[cfati@CFATI-5510-0:e:\Work\Dev\StackOverflow\q070103258]> "e:\Work\Dev\VEnvs\py_pc064_03.08.07_test0\Scripts\python.exe" code00.py Python 3.8.7 (tags/v3.8.7:6503f05, Dec 21 2020, 17:59:51) [MSC v.1928 64 bit (AMD64)] 064bit on win32 { 'Id': 9, 'Printer': 'WF-7610 Series(Network)', 'User': 'cfati', 'Document': '*Untitled - Notepad', 'Index': 1, 'Pages': 1, 'Created': pywintypes.datetime(2021, 12, 3, 22, 52, 22, 923000, tzinfo=TimeZoneInfo('GMT Standard Time', True)), 'Format': 'A4', 'Color': 'Color', 'Status': None} { 'Id': 13, 'Printer': 'WF-7610 Series(Network)', 'User': 'cfati', 'Document': 'e:\\Work\\Dev\\StackOverflow\\q070103258\\code00.py', 'Index': 2, 'Pages': 4, 'Created': pywintypes.datetime(2021, 12, 3, 23, 10, 40, 430000, tzinfo=TimeZoneInfo('GMT Standard Time', True)), 'Format': 'A3', 'Color': 'Monochrome', 'Status': None} Done.

Grapically:

Notes:

  • Data is retrieved using [MS.Docs]: EnumJobs function (mainly from [MS.Docs]: JOB_INFO_2 structure)

  • As I specified, some of the requested items are not present (finish printing time), and won't be be using this approach. For those ones, [SO]: How to catch printer event in python (@ErykSun's answer) can be used (I tried it for some events, and it works). Unfortunately PyWin32 does not wrap all the print APIs, so printer / job notification functions family (e.g. FindFirstPrinterChangeNotification) should still be called via [Python.Docs]: ctypes - A foreign function library for Python

  • Print jobs from other computers: this is a whole different animal.
    OpenPrinter function opens the printer on the local machine (by default), and only gets the local queue. I'm not sure how (or whether it's possible) to get all of them. I think that code should not need changes, only setting the computer as a print server (and pass that name as OpenPrinter's 1st argument) from [MS.Docs]: Configure Print and Document Services (but this is an untested assumption)

Toplist

Neuester Beitrag

Stichworte