从Windows命令行打印PDF文件

33

我想打印当前目录中的所有pdf文件。 当我在cmd中调用此bash脚本(singlepdf.sh)时: '"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe"' /t Gemeinde_348_BioID_842_alt.pdf一切正常。

当使用以下内容调用multiplepdfs.sh时:

declare -a pdfs=(*.pdf)

for pdf in ${pdfs[@]}; do
  echo -e "\nprinting **$pdf** with AcroRd32.exe...\n"
  '"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe"' /t $pdf
  sleep 3
done

回显显示循环中的文件被正确地寻址,但是接着我收到了错误信息"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe": No such file or directory

有人可以帮忙解决这个问题吗?

编辑: 顺便说一下,我已经安装了msys mingw。

12个回答

49
我知道这是一个老问题,但最近我也遇到了同样的问题,而且没有一个答案对我有用:
- 找不到旧版本的Foxit Reader - 如@pilkch所说,2Printer会添加一个报告页面 - Adobe Reader会打开一个图形界面
在进一步搜索后,我找到了这个:https://github.com/svishnevsky/PDFtoPrinter
这是一个简单的可执行文件,你可以通过调用文件名来打印到默认打印机(或指定的打印机)。 从该网站上可以看到:
“PDFtoPrinter是一个用于从Windows命令行打印PDF文件的程序。该程序通常设计用于Windows命令行,也可与vDos DOS模拟器一起使用。”
要将PDF文件打印到默认的Windows打印机,请使用以下命令:
PDFtoPrinter.exe filename.pdf

要打印到特定的打印机,请在引号中添加打印机的名称。
PDFtoPrinter.exe filename.pdf "Name of Printer"

如果你想要打印到网络打印机,请使用在Windows打印对话框中显示的名称,就像这样(注意名称开头的两个反斜杠和服务器名后面的单个反斜杠)。
PDFtoPrinter.exe filename.pdf "\\SERVER\PrinterName"

22
我是PDFtoPrinter.exe的作者。它是用AutoIt编写的,一些病毒扫描程序会把任何AutoIt可执行文件标记为特洛伊木马,因为脚本小子使用AutoIt。建议您尝试将其提交到VirusTotal.com或viruscan.jotti.org以获取更及时的报告。 - emendelson
1
@ThorstenSchöning - 是的,PDFtoPrinter使用AutoIt的“RunWait”来运行嵌入的PDF-Xchange Viewer。关于这个程序,欢迎您通过页面底部的地址与我联系;在公开之前,我宁愿清理掉荒谬的AutoIt代码混乱,但如果您愿意私下查看它,请联系我。同时,我已经发布了一个命令行界面版本,名为PDFtoPrinterCLI.exe(同一网站),您可以尝试一下。我不知道它是否有帮助,请告诉我。 - emendelson
1
@ThorstenSchöning - 还可以查看我的网页上的调试选项。如果您使用它,它会显示如何运行打印命令,您可能根本不需要我的程序。 - emendelson
1
哥伦比亚大学的原始链接现在是404,但在这个C#包装器中有exe的副本:https://github.com/svishnevsky/PDFtoPrinter - undefined
1
已更新答案中的链接 - undefined
显示剩余14条评论

12

我使用Acrobat Reader进行这项任务时遇到了两个问题。

  1. 命令行API没有官方支持,因此可能会在没有警告的情况下更改或删除。
  2. 发送打印命令给Reader会加载GUI界面,似乎没有办法防止。我需要进程对用户透明。

我偶然发现了这篇博客,建议使用Foxit Reader。 Foxit Reader是免费的,API几乎与Acrobat Reader相同,但至关重要的是有文档记录,且不会为打印作业加载GUI界面。

一个警告,不要只是在安装过程中点击,注意一下,它还会试图安装无关软件。为什么软件供应商还在这样做???


9
我无法使 Foxit Reader(v7.0.6)在后台默默打印。它会打开 GUI 的最小化版本,并且直到手动关闭后才会返回控制权 :( 所以我最终使用了 SumatraPDF,该程序具有命令行开关 -print-to-default(或 -print-to _myprinter_)和 -silent,可实现完全静默的后台打印!如果成功,返回代码为 0,否则为 1。参考:http://github.com/sumatrapdfreader/sumatrapdf/wiki/Command-line-arguments - Johan
1
除了上述第7.06点所述的问题之外,开关也已更改。以前,只有/t用于静默打印,并且打印机名称是可选的。如果省略了打印机名称,Foxit将文件发送到默认打印机。现在,/p已被指定为发送到默认打印机,而/t需要有一个命名的打印机。 - wastubbs
2
如果你想在横向媒体上打印横向PDF文件,SumatraPDF就是个垃圾!它会自动旋转你的PDF文件。 - LittleTreeX
1
v7的问题已经确认为一个bug。http://forums.foxitsoftware.com/forum/portable-document-format-pdf-tools/foxit-reader/149617-print-pdf-via-command-line-and-exit-foxit-reader - David Anderson
2
根据您的使用情况,Adobe Reader许可证不允许在无头或从服务器打印或打印时使用。如果您需要进行批量打印并且需要速度,则SumatraPDF速度较慢。从SumatraPDF论坛上来看:“总的来说,Sumatra不擅长打印,因此我不建议在[高容量场景]中使用它。目前,我们通过为每个页面生成位图并将这些位图发送到打印机来进行打印。Adobe更加智能。” - HK1
显示剩余3条评论

6
错误信息在告诉你什么。
尝试只使用:
"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe" /t "$pdf"

当您将字符串用单引号括起来时,这会使内部的所有内容都成为有效字符串,包括 " 字符。通过去掉单引号,shell 将处理双引号作为字符串 "包装器"。
我还建议将文件名变量用双引号括起来,这样您可以轻松处理名称中带有空格的文件,例如:
"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe" /t "$pdf"

IHTH


我尝试了每一种引号的类型和变化,但只有在循环外面使用的那个才有效。使用单引号时,Adobe 打开文件,但奇怪的是会出现类似于“打开文件时出错”的消息,并且不会将文件发送到打印机。 - Kay
感谢您的编辑,我只是在发布问题,询问如何在Windows上运行bash。我能推荐的最好方法是在脚本顶部添加set -vx,这样您就可以看到正在执行什么以及变量使用了哪些值。此外,您可以尝试使用ANSI字符串,例如$"c:\program ...."$'c:\.....',而不仅仅是普通的双引号或单引号。还要在您的帖子中添加bash --version的输出。祝你好运。 - shellter
或者尝试让您的“multipdf”脚本使用文件参数调用“singlepdf”?祝好运。 - shellter

6

看起来你缺少打印机名称、驱动程序和端口 - 按顺序依次输入。你的最终命令应该是:

AcroRd32.exe /t <file.pdf> <printer_name> <printer_driver> <printer_port>

例如:

"C:\Program Files (x86)\Adobe\Reader 11.0\Reader\AcroRd32.exe" /t "C:\Folder\File.pdf" "Brother MFC-7820N USB Printer" "Brother MFC-7820N USB Printer" "IP_192.168.10.110"

注意:要查找打印机信息,请右键单击打印机并选择属性。在我上面显示的情况下,打印机名称和驱动程序名称匹配 - 但您的信息可能不同。

3
以下批处理脚本应该可以实现您想要的功能。虽然在完成后会留下一个Acrobat Reader实例运行,但这不会对下次运行此脚本造成任何问题。
@echo off
for %%f in (*.pdf) do (
  echo Printing %cd%\%%f with Adobe Acrobat Reader...
  start /b "Printing %%f" "C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe" /p /h "%cd%\%%f"
)

虽然您可以随后单独终止Acrobat Reader进程,但有可能会关闭其他您不想关闭的已打开PDF文档。


使用选项 /p/h 可以很好地解决问题——如果使用 Acrobat 进行打印。 - Mikolaj

3

首先,我非常愿意为这个有帮助的社区做出贡献...

为了给那些仍在寻找简单解决方案的人提供帮助,我使用了一个免费的Foxit软件产品 - FoxItReader。
以下是使用静默打印功能的版本链接 - 较新版本的静默打印功能仍未正常工作。 FoxitReader623.815_Setup

FOR %%f IN (*.pdf) DO ("C:\Program Files (x86)\Foxit Software\Foxit Reader\FoxitReader.exe" /t %%f "SPST-SMPICK" %%f & del %%f) 

我只是创建了一个命令来循环遍历目录,并对每个pdf文件(FOR %%f IN *.pdf)静默打开阅读器(/t),获取下一个PDF(%%f)并将其发送到打印队列(SPST-SMPICK),然后在将每个PDF发送到打印队列后删除它(del%%f)。如果您需要将文件移动到另一个目录,Shashank展示了一个示例。
FOR %%X in ("%dir1%*.pdf") DO (move "%%~dpnX.pdf" p/)

2

使用Acrobat Reader并不是一个好的解决方案,特别是命令行属性没有文档记录。此外,Acrobat Reader的窗口在打印过程后仍然保持打开状态。PDF文件已经被打印机驱动程序广泛支持,因此您可以找到更好的工具,例如2Printer.exe或RawFilePrinter.exe。在我看来,RawFilePrinter具有更好的支持和清晰的许可流程(您只需支付一次捐款,就可以在许多项目中重新分发RawFilePrinter - 即使新版本也可以与先前购买的许可证一起使用)

RawFilePrinter.exe -p "c:\Users\Me\Desktop\mypdffile.pdf" "Canon Printer" 
IF %ERRORLEVEL% 1(
    echo "Error!"
)

最新版本下载链接: http://bigdotsoftware.pl/index.php/rawfileprinter


2

我曾经遇到过一样的问题,需要连续打印多个PDF文件,后来我通过使用2Printer软件找到了解决方案。 以下是用命令行打印PDF文件的示例:

2Printer.exe -s "C:\In\*.PDF" -prn "HP LasetJet 1100"

该软件可免费用于非商业用途,网址为http://doc2prn.com/


5
免费版本会在每个页面上添加一个报告页,因此对我来说有点无用,因为我的印刷品有50%会浪费。 - pilkch
只要它能工作,我们就可以购买它。但请确保购买后它能正常工作。您能否确认它的可靠性和标准?我们必须在企业中使用它。 - user285594

1
这里有另一种解决方案:

1)下载SumatraPDF(便携版)- https://www.sumatrapdfreader.org/download-free-pdf-viewer.html

2)创建一个类库项目并将SumatraPDF.exe解压到项目目录根目录并取消阻止。

3)在项目属性中,转到资源选项卡并将exe文件添加为文件。

4)将以下类添加到您的库:

public class SumatraWrapper : IDisposable
{
    private readonly FileInfo _tempFileForExe = null;
    private readonly FileInfo _exe = null;

    public SumatraWrapper()
    {
        _exe = ExtractExe();
    }

    public SumatraWrapper(FileInfo tempFileForExe)
        : this()
    {
        _tempFileForExe = tempFileForExe ?? throw new ArgumentNullException(nameof(tempFileForExe));
    }

    private FileInfo ExtractExe()
    {
        string tempfile = 
            _tempFileForExe != null ? 
            _tempFileForExe.FullName : 
            Path.GetTempFileName() + ".exe";

        FileInfo exe = new FileInfo(tempfile);
        byte[] bytes = Properties.Resources.SumatraPDF;

        using (FileStream fs = exe.OpenWrite())
        {
            fs.Write(bytes, 0, bytes.Length);
        }

        return exe;
    }

    public bool Print(FileInfo file, string printerName)
    {
        string arguments = $"-print-to \"{printerName}\" \"{file.FullName}\"";
        ProcessStartInfo processStartInfo = new ProcessStartInfo(_exe.FullName, arguments)
        {
            CreateNoWindow = true
        };
        using (Process process = Process.Start(processStartInfo))
        {
            process.WaitForExit();
            return process.ExitCode == 0;
        }
    }

    #region IDisposable Support
    private bool disposedValue = false; // To detect redundant calls

    protected virtual void Dispose(bool disposing)
    {
        if (!disposedValue)
        {
            if (disposing)
            {
                // TODO: dispose managed state (managed objects).
            }

            // TODO: free unmanaged resources (unmanaged objects) and override a finalizer below.
            // TODO: set large fields to null.
            try
            {
                File.Delete(_exe.FullName);
            }
            catch
            {

            }

            disposedValue = true;
        }
    }

    // TODO: override a finalizer only if Dispose(bool disposing) above has code to free unmanaged resources.
    // ~PdfToPrinterWrapper() {
    //   // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
    //   Dispose(false);
    // }

    // This code added to correctly implement the disposable pattern.
    public void Dispose()
    {
        // Do not change this code. Put cleanup code in Dispose(bool disposing) above.
        Dispose(true);
        // TODO: uncomment the following line if the finalizer is overridden above.
        // GC.SuppressFinalize(this);
    }
    #endregion
}

5)从您的代码中轻松打印pdf文件。

使用方法如下:

FileInfo file = new FileInfo(@"c:\Sandbox\dummy file.pdf");
SumatraWrapper pdfToPrinter =
    new SumatraWrapper();
pdfToPrinter.Print(file, "My Printer");

0
今天我正在寻找这个解决方案,我尝试了PDFtoPrinter,但出现了问题(我尝试打印的PDF建议使用不正确的纸张大小,导致打印作业挂起,直到解决为止,什么都没有打印)。 为了寻找替代方案,我想起了GhostScript和与之相关的实用程序。 我发现GSView及其相关程序GSPrint(参考https://www.ghostscript.com/)。 这两者都需要GhostScript(https://www.ghostscript.com/),但当安装了所有组件时,GSPrint可以完美地工作,并且我能够创建一个定时任务,在夜间自动打印PDF文件。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接