首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >从命令行打印图像,并在Windows上等待打印作业完成

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

Stack Overflow用户
提问于 2022-04-16 15:18:45
回答 2查看 387关注 0票数 0

我需要编写一个解决方案,在上面写入数据,然后大量打印RFID标签,每个标签都是从模板python脚本生成的.png图像,以及从数据库或excel文件中获取的数据。

要打印该程序,只需使用subprocess.check_call(print_cmd)调用相关的系统实用程序( unix系统上的CUPS),传递映像文件(保存在内存挂载的文件系统中,以减少磁盘使用量)。

现在,它也需要运行在Windows系统上,但实际上没有一个不错的系统实用程序,而且在类似问题下的解决方案command line tool for print picture?不考虑打印作业的完成,或者如果作业导致错误,所有的边距都会被扭曲,图像总是因为某种原因旋转90度。

如何在Windows中使用命令或脚本明智地打印图像,并等待它成功完成,或者在作业导致错误时返回错误?可能没有依赖关系

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2022-04-16 15:18:45

如果您可以安装依赖项,那么有许多程序提供了现成的解决方案.

(无依赖项)解决这个问题的唯一正确方法是创建一个powershell脚本来解释这个问题。

代码语言:javascript
运行
复制
[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" )

然后,我需要稍微修改打印子进程调用

代码语言:javascript
运行
复制
powershell -File "path\to\print.ps1" "C:\absolute\path\to\file.png"

然后有几个必要的设置步骤:

(discaimer,我不使用英语窗口,所以我不知道英文窃听器应该怎么称呼。我会用草书写的)

  1. 创建示例图像,右键单击,然后选择“打印

代码语言:javascript
运行
复制
- 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.

  1. 转到打印机设置,然后在“工具”下编辑打印机状态监视

代码语言:javascript
运行
复制
- 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

假设如下:

只有您的程序运行此script

  • theres,对于给定的打印机

  • ,每次只有一个打印作业打印机驱动程序不是由猴子编写的,它们实际上报告了当前正确的打印机状态

此小黑客将允许从命令中打印图像,并通过错误管理等待作业完成;并且只使用windows预装软件。

进一步的优化可以通过保持powershell子进程活动,并且只以& "path\to\print.ps1" "C:\absolute\path\to\file.png"格式传递脚本来完成,等待标准输出报告OK或KO,但只在需要大规模打印的情况下。

票数 1
EN

Stack Overflow用户

发布于 2022-11-19 15:52:48

由于不得不再次处理此问题,因此只想使用pywin32包在“纯”python中添加一个更简单的解决方案。

代码语言:javascript
运行
复制
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

有用的额外资源

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71895109

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档