从命令行打印图像,等待在Windows上完成打印作业

发布于 2025-01-21 21:39:32 字数 550 浏览 0 评论 0原文

我需要编写一个解决方案来写入数据,然后打印RFID标签en-masse,每个标签都是从模板python脚本中生成的.png映像,以及从数据库或Excel文件中获取的数据。

要打印程序,只需使用subprocess.check_call(print_cmd)传递image文件(现在保存在Ram-abounted文件系统上,用于最小磁盘使用),现在使用subprocess.check_call(print_cmd)调用相对系统实用程序(unix Systems上的杯子)

,现在它还需要在Windows系统上运行,但是实际上并没有一个不错的系统实用程序,并且在类似问题下解决方案命令行工具工具对于打印图片吗?不考虑打印作用的完成,或者如果作业导致错误,由于某种原因,将拧紧边距,并且图像始终旋转90度。

我如何使用Windows中的命令或脚本在Windows中打印图像并等待成功完成或返回错误(如果作业会导致错误)? 可能没有依赖关系

I needed to write a solution to write data on and then print RFID labels en-masse, each generated as .png images from a template python script and data taken from a database or excel file.

To print the program simply calls the relative system utility (CUPS on unix systems) using subprocess.check_call(print_cmd) passing the image file (saved on a ram-mounted file system for minimal disk usage)

Now, it also needs to run on Windows systems, but there is not really a decent system utility for that, and solutions under a similar question command line tool for print picture? don't account for print-job completion or if the job results in an error, the margins are all screwed and the image is always rotated 90 degrees for some reason.

How can I sanely print an image using a command or a script in Windows and wait for it to complete successfully or return an error if the job results in an error?
Possibly with no dependencies

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

娇妻 2025-01-28 21:39:33

如果您可以安装依赖项,则有许多程序提供解决方案。


我可以找到解决此问题的唯一理智的方法没有依赖关系是创建一个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"

一点设置步骤:(

所以我不知道应该如何称呼英语thig。

  1. 我不使用英语的Windows , 图像,右键单击,然后选择 print

    • 从打开的打印对话框中,然后设置您要使用的特定打印机的所有默认选项,例如方向,保证金,纸张类型等。
  2. 转到打印机设置,然后在工具下进行编辑打印机状态监视

    • 编辑监视频率 to “仅在打印作业期间” 。默认情况下应被禁用
    • 在下一个选项卡中,将轮询频率修改为最低可用的,在打印作业期间100ms(您可以为使用较低的,而未打印 option option

假设以下内容:

  • 只有您的程序正在运行此脚本
  • ,每次只有1个打印作业,用于给定打印机。
  • 打印机驱动程序不是由猴子写的,他们实际上报告了当前的,正确的打印机状态

这个小小的黑客将通过错误管理打印命令和等待作业的图像,并且只能使用Windows预装的软件

来进一步优化path \ to \ print.ps1“” c:\ absolute \ path \ to \ file.png“ 格式,等待标准输出报告确定或ko;但仅在需要质量打印时。

If you can install dependencies, there are many programs that offer a solution out-of-the-box.


The only sane way i could find to solve this issue with no dependencies is by creating a powershell script to account for this

[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" )

I would then need to slightly modify the print subprocess call to

powershell -File "path\to\print.ps1" "C:\absolute\path\to\file.png"

Then there are a couple of necessary setup steps:

(discaimer, I don't use windows in english so i don't know how the english thigs are supposed to be called. i will use cursive for those)

  1. create an example image, right click and then select Print

    • from the print dialog that opens then set up all the default options you want, like orientation, margins, paper type, etc etc for the specific printer you're gonna use.
  2. Go to printer settings, under tools then edit Printer Status Monitoring

    • edit monitoring frequency to "only during print jobs". it should be disabled by default
    • in the next tab, modify polling frequency to the minimum available, 100ms during print jobs (you can use a lower one for the while not printing option

Assuming the following:

  • only your program is running this script
  • theres always only 1 printing job at a time for a given printer
  • the printer drivers were not written by a monkey and they actually report the current, correct printer status

This little hack will allow to print an image from a command and await job completion, with error management; and uses only windows preinstalled software

Further optimization could be done by keeping powershell subprocess active and only passing it scripts in the & "path\to\print.ps1" "C:\absolute\path\to\file.png" format, waiting for standard output to report an OK or a KO; but only if mass printing is required.

庆幸我还是我 2025-01-28 21:39:33

不得不再次对此进行处理,只想使用pywin32软件包在“纯” 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


方案

Having had to work on this again, just wanted to add a simpler solution in "pure" python using the pywin32 package

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


useful additional resources

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文