[英]print an image from command line and await print job completion on Windows
我需要编写一个解决方案来写入数据,然后批量打印 RFID 标签,每个标签都从模板 python 脚本和从数据库或 excel 文件中获取的数据生成 as.png 图像。
要打印程序,只需调用相关系统实用程序(unix 系统上的 CUPS),使用subprocess.check_call(print_cmd)
传递图像文件(保存在 ram 安装的文件系统上,以尽量减少磁盘使用)
现在,它还需要在 Windows 系统上运行,但实际上并没有一个像样的系统实用程序,以及类似问题的打印图片命令行工具下的解决方案? 不要考虑打印作业的完成情况,或者如果作业导致错误,则页边距都被拧紧并且图像由于某种原因总是旋转 90 度。
如何使用 Windows 中的命令或脚本理智地打印图像并等待它成功完成或在作业出错时返回错误? 可能没有依赖关系
如果您可以安装依赖项,则有许多程序可以提供开箱即用的解决方案。
我能找到解决这个问题的唯一明智的方法是创建一个powershell脚本来解决这个问题
[CmdletBinding()]
param (
[string] $file = $(throw "parameter is mandatory"),
[string] $printer = "EXACT PRINTER NAME HERE"
)
$ERR = "UserIntervention|Error|Jammed"
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
# https://stackoverflow.com/a/20402656/17350905
# only sends the print job to the printer
rundll32 C:\Windows\System32\shimgvw.dll,ImageView_PrintTo $file $printer
# wait until printer is in printing status
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Printing" )
# wait until printing is done
do {
$status = (Get-Printer -Name $printer).PrinterStatus.ToString()
if ($status -match $ERR){ exit 1 }
Start-Sleep -Milliseconds 100
} until ( $status -eq "Normal" )
然后我需要稍微修改打印子进程调用
powershell -File "path\to\print.ps1" "C:\absolute\path\to\file.png"
然后是几个必要的设置步骤:
(免责声明,我不使用英语 windows,所以我不知道应该如何称呼英语 thigs。我将使用草书)
创建示例图像,右键单击然后 select打印
Go到打印机设置,工具下然后编辑打印机状态监控
假设如下:
这个小技巧将允许从命令打印图像并等待作业完成,并进行错误管理; 并且仅使用 windows 预装软件
可以通过保持 powershell 子进程处于活动状态并仅以& "path\to\print.ps1" "C:\absolute\path\to\file.png"
格式向其传递脚本来完成进一步优化,等待标准 output 报告一个OK 或 KO; 但前提是需要大量印刷。
不得不再次处理这个问题,只是想使用pywin32
package 在“纯”python 中添加一个更简单的解决方案
import time
import subprocess
from typing import List
try:
import win32print as wprint
PRINTERS: List[str] = [p[2] for p in wprint.EnumPrinters(wprint.PRINTER_ENUM_LOCAL)]
PRINTER_DEFAULT = wprint.GetDefaultPrinter()
WIN32_SUPPORTED = True
except:
print("[!!] an error occured while retrieving printers")
# you could throw an exception or whatever
# bla bla do other stuff
if "WIN32_SUPPORTED" in globals():
__printImg_win32(file, printer_name)
def __printImg_win32(file: str, printer: str = ""):
if not printer:
printer = PRINTER_DEFAULT
# verify prerequisites here
# i still do prefer to print calling rundll32 directly,
# because of the default printer settings shenaningans
# and also because i've reliably used it to spool millions of jobs
subprocess.check_call(
[
"C:\\Windows\\System32\\rundll32",
"C:\\Windows\\System32\\shimgvw.dll,ImageView_PrintTo",
file,
printer,
]
)
__monitorJob_win32(printer)
pass
def __monitorJob_win32(printer: str, timeout=16.0):
p = wprint.OpenPrinter(printer)
# wait for job to be sheduled
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
# unsure about those flags, but definitively not errors.
# it seems they are "moving paper forward"
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] > 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout sheduling job!")
# await job completion
t0 = time.time()
while (time.time()-t0) < timeout:
ptrr = wprint.GetPrinter(p, 2)
if ptrr["Status"] != 0 and ptrr["Status"] not in [1024,1048576]:
raise Error("Printer is in error (status %d)!" % ptrr["Status"])
if ptrr["cJobs"] == 0 and ptrr["Status"] == 0:
break
time.sleep(0.1)
else:
raise Error("Printer timeout waiting for completion!")
wprint.ClosePrinter(p)
return
有用的额外资源
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.