Modify document when printing in Windows by create virtual printer
Last active
May 27, 2022 11:09
-
-
Save Thong-Tran/04eed7ce2d31e7e08f1b8623e5c7f102 to your computer and use it in GitHub Desktop.
Modify document by vitual printer
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import subprocess | |
import socket | |
import select | |
# pywin32 extension | |
import win32print | |
import pywintypes | |
HOST = '127.0.0.1' # Standard loopback interface address (localhost) | |
PORT = 8888 # Port to listen on (non-privileged ports are > 1023) | |
PRINTER_NAME = 'Virtual Printer' | |
def create_port_printer(host: str, port: int): | |
'''Register tcp port for printer, using `cscript prnport.vbs`''' | |
create_port_cmd = 'cscript c:\\Windows\\System32\\Printing_Admin_Scripts\\en-US\\prnport.vbs -a -r {ip}:{port} -h {ip} -o raw -n {port}' | |
subprocess.check_output(create_port_cmd.format(ip=host, port=port), shell=True) | |
def create_printer(printer_name: str, host: str, port: int, driver_name='Microsoft Software Printer Driver') -> object: | |
'''Create a new printer, if exist return it''' | |
try: | |
return win32print.OpenPrinter(printer_name) | |
except pywintypes.error as e: | |
pass | |
printer_info = { | |
'pPrinterName': printer_name, | |
'pDevMode': pywintypes.DEVMODEType(), | |
'pDriverName': driver_name, | |
'pPortName': f'{host}:{port}', | |
'pPrintProcessor': 'WinPrint', | |
'Attributes': 0, | |
'AveragePPM': 0, | |
'cJobs': 0, | |
'DefaultPriority': 0, | |
'Priority': 0, | |
'StartTime': 0, | |
'Status': 0, | |
'UntilTime': 0, | |
'pComment': '', | |
'pLocation': '', | |
'pDatatype': None, | |
'pParameters': None, | |
'pSecurityDescriptor': None, | |
'pSepFile': None, | |
'pServerName': None, | |
'pShareName': None | |
} | |
h_printer = win32print.AddPrinter(None, 2, printer_info) | |
return h_printer | |
def send_to_printer(raw_data: bytes, printer='Microsoft Print to PDF', out_file='out_file'): | |
'''Send XPS data to printer''' | |
hPrinter = win32print.OpenPrinter(printer) | |
try: | |
hJob = win32print.StartDocPrinter(hPrinter, 1, (out_file, None, "RAW")) | |
try: | |
win32print.StartPagePrinter(hPrinter) | |
win32print.WritePrinter(hPrinter, raw_data) | |
win32print.EndPagePrinter(hPrinter) | |
finally: | |
win32print.EndDocPrinter(hPrinter) | |
finally: | |
win32print.ClosePrinter(hPrinter) | |
def run_server(host: str, port: int): | |
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as server_socket: | |
server_socket.bind((host, port)) | |
server_socket.listen() | |
print("Listening ...") | |
try: | |
while True: | |
readable, _, _ = select.select([server_socket], [], [], 1) | |
for s in readable: | |
raw = b'' | |
client_socket, address = s.accept() | |
print('Connected by', address) | |
while True: | |
data = client_socket.recv(1024) | |
if data: | |
raw += data | |
else: | |
client_socket.close() | |
break | |
# Modify data | |
xps_bytes = raw | |
# Reprint it | |
send_to_printer(xps_bytes) | |
except KeyboardInterrupt: | |
print('Closing ...') | |
if __name__ == "__main__": | |
create_port_printer(HOST, PORT) | |
create_printer(PRINTER_NAME, HOST, PORT) | |
run_server(HOST, PORT) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment