C# 使用Adobe Acrobat以静默方式打印PDF

C# 使用Adobe Acrobat以静默方式打印PDF,c#,acrobat,C#,Acrobat,当我试图使用AdobeAcrobat以C#的形式以静默方式打印pdf时,我遇到了两个问题。我正在使用Process.Start()打印PDF 第一个问题是,如果不指定可执行文件的完整路径,我无法启动Adobe Acrobat。我假设在安装时它不会将其添加到您的路径中有没有一种简单的方法可以在机器上启动acrobat的最新版本而不指定完整路径名?我担心客户端会进行更新,并破坏启动该版本的代码。我还关心他们在具有不同版本windows的计算机上安装此软件(64位环境下的安装路径与32位环境下的安装路

当我试图使用AdobeAcrobat以C#的形式以静默方式打印pdf时,我遇到了两个问题。我正在使用Process.Start()打印PDF

第一个问题是,如果不指定可执行文件的完整路径,我无法启动Adobe Acrobat。我假设在安装时它不会将其添加到您的路径中有没有一种简单的方法可以在机器上启动acrobat的最新版本而不指定完整路径名?我担心客户端会进行更新,并破坏启动该版本的代码。我还关心他们在具有不同版本windows的计算机上安装此软件(64位环境下的安装路径与32位环境下的安装路径不同)

我的第二个问题是,每当我启动acrobat并打印它时,acrobat窗口仍然是打开的。我认为我使用的命令行参数会抑制所有这些,但显然不是

我尝试使用以下语法从命令行启动adobe acrobat:

C:\ProgramFiles(x86)\Adobe\Reader 10.0\Reader>AcroRd32.exe/t“Label.pdf”“HP4000”“HP LaserJet 4100系列PCL6”“out.pdf”

打印出来的效果很好,但仍保持acrobat窗口向上除了以编程方式退出并终止进程之外,还有其他解决方案吗?

问题1 你可以在注册中心工作。在
HKEY\U CLASSES\U ROOT\.pdf\PersistentHandler\(默认)
中,您应该找到一个CLSID,它指向在两个位置之一找到的值。同一密钥的CLSID文件夹,或者(对于64位系统)在
Wow6432Node\CLSID
中,然后在该CLSID的密钥中执行一步

在该键中,您可以查找
LocalServer32
,并找到指向当前exe路径的默认字符串值

我并不是百分之百地支持这些,但似乎是合理的(尽管您必须在多个环境中进行验证,以确认是否确实找到了您正在寻找的流程)

(以下是有关的文件)

问题2 可能是使用StartInfo的过程

Process p = new Process();
p.StartInfo.FileName = @"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRd32.exe";
p.StartInfo.Arguments = "/t \"Label.pdf\" \"HP4000\" \"HP LaserJet 4100 Series PCL6\" \"out.pdf\"";
p.CreateNoWindow = true;
p.Start();
p.WaitForExit();

(虽然只是猜测,但我相信一点测试就会证明它有效/无效)

我最终放弃了Adobe Acrobat,转而使用(免费pdf阅读器)进行pdf打印。这是我在C#中通过FoxIt打印的代码:

上述代码打印到默认打印机,但有一些命令行参数可用于指定文件和打印机。您可以使用以下语法:

Foxit Reader.exe-t“pdf文件名”“打印机名称”

更新: 显然,acrobat的早期版本也没有上述问题。如果您使用更旧的版本(4.x或类似的版本),则不会出现此问题

有些打印机也支持原生pdf打印,因此可以将原始pdf数据发送到打印机并进行打印。有关向打印机发送原始数据的信息,请参阅

更新2 在我们软件的后续版本中,我们最终使用了付费产品:


如果您使用Acrobat reader 4.0,您可以执行以下操作: “C:\Program Files\Adobe\Acrobat 4.0\Reader\Acrord32.exe”/t/s“U:\PDF\U MS\SM003067K08.PDF”计划
但是,如果PDF文件是在较新版本的Acrobat中创建的,则会打开一个不可见窗口。

获得另一个解决方案。。它是stackOverflow中其他代码段的组合。当我调用CloseMainWindow,然后调用Kill。。adobe关闭

    Dim info As New ProcessStartInfo()
    info.Verb = "print"
    info.FileName = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("Software").OpenSubKey("Microsoft").OpenSubKey("Windows").OpenSubKey("CurrentVersion").OpenSubKey("App Paths").OpenSubKey("AcroRd32.exe").GetValue(String.Empty).ToString()
    info.Arguments = String.Format("/p /h {0}", "c:\log\test.pdf")
    info.CreateNoWindow = True
    info.WindowStyle = ProcessWindowStyle.Hidden
    info.UseShellExecute = False

    Dim p As Process = Process.Start(info)
    p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden

    Dim counter As Integer = 0
    Do Until p.HasExited
        System.Threading.Thread.Sleep(1000)
        counter += 1
        If counter = 5 Then
            Exit Do
        End If
    Loop
    If p.HasExited = False Then
        p.CloseMainWindow()
        p.Kill()
    End If

在Acrobat Reader 8.1.3和Acrobat Pro 11.0.06中测试了以下各项,并确认了以下功能:

  • 查找系统上的默认Acrobat可执行文件
  • 将文件发送到本地打印机
  • 关闭Acrobat,无论版本如何

  • 尼克的回答我觉得不错,所以我把它翻译成c。它起作用了

    using System.Diagnostics;
    
    namespace Whatever
    {
    static class pdfPrint
    {
        public static void pdfTest(string pdfFileName)
        {
           string processFilename = Microsoft.Win32.Registry.LocalMachine
                .OpenSubKey("Software")
                .OpenSubKey("Microsoft")
                .OpenSubKey("Windows")
                .OpenSubKey("CurrentVersion")
                .OpenSubKey("App Paths")
                .OpenSubKey("AcroRd32.exe")
                .GetValue(String.Empty).ToString();
    
            ProcessStartInfo info = new ProcessStartInfo();
            info.Verb = "print";
            info.FileName = processFilename;
            info.Arguments = String.Format("/p /h {0}", pdfFileName);
            info.CreateNoWindow = true;
            info.WindowStyle = ProcessWindowStyle.Hidden; 
            //(It won't be hidden anyway... thanks Adobe!)
            info.UseShellExecute = false;
    
            Process p = Process.Start(info);
            p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
    
            int counter = 0;
            while (!p.HasExited)
            {
                System.Threading.Thread.Sleep(1000);
                counter += 1;
                if (counter == 5) break;
            }
            if (!p.HasExited)
            {
                p.CloseMainWindow();
                p.Kill();
            }
        }
    }
    

    }

    我试过AdobeReader和Foxit,但运气不佳。目前这两个版本都非常喜欢弹出窗口,让进程运行。最后用了一种非常不显眼的方式。这是我使用的代码。打印完成后,没有任何窗口和进程的痕迹可以很好地退出

        public static void SumatraPrint(string pdfFile, string printer)
        {
            var exePath = Registry.LocalMachine.OpenSubKey(
                @"SOFTWARE\Microsoft\Windows\CurrentVersion" +
                @"\App Paths\SumatraPDF.exe").GetValue("").ToString();
    
            var args = $"-print-to \"{printer}\" {pdfFile}";
    
            var process = Process.Start(exePath, args);
            process.WaitForExit();
        }
    

    您已经尝试过与Acrobat Reader不同的东西,所以我的建议是,忘记GUI应用程序,使用第三方命令行工具,如RawFilePrinter.exe

    private static void ExecuteRawFilePrinter() {
        Process process = new Process();
        process.StartInfo.FileName = "c:\\Program Files (x86)\\RawFilePrinter\\RawFilePrinter.exe";
        process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        process.StartInfo.Arguments = string.Format("-p \"c:\\Users\\Me\\Desktop\\mypdffile.pdf\" \"Canon Printer\"");
    
        process.Start();
        process.WaitForExit();
        if (process.ExitCode == 0) {
                //ok
        } else {
                //error
        }
    }
    

    要下载的最新版本:

    用于问题2

    使用/h参数将在最小化窗口中打开Acrobat或Adobe Reader

    例如:
    C:\ProgramFiles(x86)\Adobe\Reader 10.0\Reader>AcroRd32.exe**/h**/t“Label.pdf”“HP4000”“HP LaserJet 4100系列PCL6”“out.pdf”


    相关文档:

    但是,即使这确实阻止了它的显示,进程是否仍在运行(例如,您可以在TaskManager中看到它)?@Chad:我从来没有幸运地打印PDF,并在谷歌上搜索过所有解决方案。我想用您基本上想要做的事情来自动化一个内部任务,但由于缺少文档、关闭应用程序的问题或太多的变化而最终放弃了。您可能只需要获得一个PDF库,该库可以“内部呈现”文件,并通过应用程序直接将其发送到打印,但大多数用于这类工作的库都需要花钱。对于问题2,我尝试了这个方法,但它无法按我希望的方式工作。在我手动关闭acrobat窗口之前,它基本上一直挂在WaitForExit()上。我尝试使用WaitForInputIdle()然后对process对象执行Kill(),但它在打印发生之前将其杀死。CreateNoWindow似乎对是否显示窗口也没有影响。@Cole W,是的,WaitForInputle()技巧对X之前的版本有效,但他们“修复”了这一点。我想他们是认真的,希望自己的窗口打开,并一直打开直到用户关闭。这救了我的命!我已经尝试了很多方法来愚蠢地打印PDF。。
        public static void SumatraPrint(string pdfFile, string printer)
        {
            var exePath = Registry.LocalMachine.OpenSubKey(
                @"SOFTWARE\Microsoft\Windows\CurrentVersion" +
                @"\App Paths\SumatraPDF.exe").GetValue("").ToString();
    
            var args = $"-print-to \"{printer}\" {pdfFile}";
    
            var process = Process.Start(exePath, args);
            process.WaitForExit();
        }
    
    private static void ExecuteRawFilePrinter() {
        Process process = new Process();
        process.StartInfo.FileName = "c:\\Program Files (x86)\\RawFilePrinter\\RawFilePrinter.exe";
        process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
        process.StartInfo.Arguments = string.Format("-p \"c:\\Users\\Me\\Desktop\\mypdffile.pdf\" \"Canon Printer\"");
    
        process.Start();
        process.WaitForExit();
        if (process.ExitCode == 0) {
                //ok
        } else {
                //error
        }
    }