如何使用 C# 打印 PDF

Posted

技术标签:

【中文标题】如何使用 C# 打印 PDF【英文标题】:How to print a PDF with C# 【发布时间】:2012-07-19 17:54:50 【问题描述】:

我试图解决这个问题将近 2 天。网上有很多或多或少的好解决方案,但没有一个完全适合我的任务。

任务:

以编程方式打印 PDF 使用固定打印机进行操作 不要让用户执行多次 Button_Click 保持沉默 - 越多越好 做客户端

第一个解决方案:

使用 Forms.WebBrowser 进行操作

如果我们安装了 Adob​​e Reader,有一个插件可以在网络浏览器中显示 PDF。有了这个解决方案,我们有一个很好的预览,并且有了 webbrowserControlName.Print(),我们可以触发控件来打印它的内容。

问题 - 我们还有一个 PrintDialog。


使用启动参数启动 AcroRd32.exe

下面的 CMD 命令让我们使用 Adob​​e Reader 来打印我们的 PDF。

InsertPathTo..\AcroRd32.exe /t "C:\sample.pdf" "\printerNetwork\printerName"

问题 - 我们需要 AcroRd32.exe 的绝对路径 |有一个 Adob​​e Reader 窗口打开,必须打开它,直到打印任务准备好。


使用 Windows 预设

Process process = new Process();

process.StartInfo.FileName = pathToPdf; 
process.StartInfo.Verb = "printto";
process.StartInfo.Arguments = "\"" + printerName + "\""; 
process.Start();

process.WaitForInputIdle();
process.Kill();

问题 - 仍然会弹出一个 Adob​​e Reader 窗口,但打印完成后它通常会自行关闭。

解决方案 - 说服客户使用 Foxit Reader(不要使用最后两行代码)。


将 PDF 页面转换为 Drawing.Image

我不知道如何使用代码来完成,但是当我让它工作时,剩下的只是小菜一碟。 Printing.PrintDocument 可以满足所有需求。


有人想从那些 PDF 中获取一些 Drawing.Image 或其他方法吗?

最好的问候, 最大

【问题讨论】:

试试Print existing PDF (or other files) in C#。 要获取 Drawing.Image,您可以查看此示例:ghostscriptnet.codeplex.com/SourceControl/… 这是几年后的事了……你能弄清楚Drawing.Image 路线吗? @B.K.可悲的是没有 - 但今天可能有更好的方法 @Max 我已经找了好几个月了,但我还没有找到一个不涉及在客户端机器上安装东西的解决方案......在我的情况下这不是一个选项. 【参考方案1】:

我能找到的最灵活、最简单、性能最好的方法是使用 GhostScript。它可以通过打印机名称直接打印到windows打印机。

"C:\Program Files\gs\gs9.07\bin\gswin64c.exe" -dPrinted -dBATCH -dNOPAUSE -sDEVICE=mswinpr2 -dNoCancel -sOutputFile="%printer%打印机名称 " "pdfdocument.pdf"

添加这些开关可将文档缩小为 A4 页面。

-sPAPERSIZE=a4 -dPDFFitPage

【讨论】:

我建议为此使用 Ghostscript 包装器。比如:ghostscriptnet.codeplex.com @HABJAN 感谢您的建议,看起来确实很有用。 我使用了 Ghostscript.NET(可通过 NuGet 获得)。当我尝试最新版本的ghostscript(9.18)时,我收到了内存访问异常。我卸载了 9.18,发现 Ghostscript.NET 上次构建之前的最新版本是 9.15。一旦我安装了它,一切似乎都开始工作了。您可以在downloads.ghostscript.com/public 获取先前版本的 ghostscript Ghostscript 的 mswinpr2 质量相当差 - 它将输入的 PDF 文件转换为光栅文件并打印出来。更好的方法是使用 3rd 方组件或尝试自己实现某些东西,尤其是打印机众所周知的 PDF/PS。在这里我找到了简单而漂亮的命令行工具effisoft.pl/rawfileprinter【参考方案2】:

另一种方法是使用 .NET 中的假脱机功能将预先格式化的打印机数据发送到打印机。但不幸的是,您需要使用 win32 spooler API

你可以看看How to send raw data to a printer by using Visual C# .NET

只有当打印机本身支持 PDF 文档时,才能使用此方法。

【讨论】:

我在回答中没有提到的好点。我会更新答案,但可能是 OP 需要的? 好点,但我不能确定所有打印机都支持它。即使目前所有的打印机都支持它,如果他们购买没有此功能的其他产品也会有问题。 链接现在转到 404。【参考方案3】:

如果可以选择商业库,您可以尝试使用Amyuni PDF Creator. Net.

直接使用库打印: 要打开 PDF 文件并直接发送打印,您可以使用方法IacDocument.Print。 C# 中的代码将如下所示:

// Open PDF document from file<br>
FileStream file1 = new FileStream ("test.pdf", FileMode.Open, FileAccess.Read);
IacDocument doc1 = new IacDocument (null);
doc1.Open (file1, "" );
// print document to a specified printer with no prompt
doc1.Print ("My Laser Printer", false);

导出为图像(然后在需要时打印): 选择 1:您可以使用方法IacDocument.ExportToJPeg 将 PDF 中的所有页面转换为可以使用 Drawing.Image 打印或显示的 JPG 图像

选择 2:您可以使用方法 IacDocument.DrawCurrentPage 和方法 System.Drawing.Graphics.FromImage 将每个页面绘制成位图。 C# 中的代码应如下所示:

FileStream myFile = new FileStream ("test.pdf", FileMode.Open, FileAccess.Read);
IacDocument doc = new IacDocument(null);
doc.Open(myFile);
doc.CurrentPage = 1;
Image img = new Bitmap(100,100);
Graphics gph = Graphics.FromImage(img);
IntPtr hdc = gph.GetHDC();
doc.DrawCurrentPage(hdc, false);
gph.ReleaseHdc( hdc );

免责声明:我为 Amyuni Technologies 工作

【讨论】:

【参考方案4】:

您可以使用ghostscript 将PDF 转换为图像格式。

以下示例将单个 PDF 转换为 PNG 文件序列:

private static void ExecuteGhostscript(string input, string tempDirectory)

    // %d will be replaced by ghostscript with a number for each page
    string filename = Path.GetFileNameWithoutExtension(input) + "-%d.png";
    string output = Path.Combine(tempDirectory, filename);

    Process ghostscript = new Process();
    ghostscript.StartInfo.FileName = _pathToGhostscript;
    ghostscript.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

    ghostscript.StartInfo.Arguments = string.Format(
        "-dSAFER -dBATCH -dNOPAUSE -sDEVICE=png16m -r300 -sOutputFile=\"0\" \"1\"", output, input);

    ghostscript.Start();
    ghostscript.WaitForExit();

如果您更喜欢使用 Adob​​e Reader,您可以隐藏它的窗口:

process.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;

【讨论】:

【参考方案5】:

我发现使用 printto 动词的代码版本略有不同。我没试过,但也许对你有帮助:

http://vbcity.com/forums/t/149141.aspx

【讨论】:

好的,刚刚看到这行不通:Adobe 的论坛说,新版本的 Adob​​e Reader 不允许您打印“静默”、“出于安全原因”(当然,Adobe)...总会有一个窗口。【参考方案6】:

我知道标签有Windows Forms;但是,由于通用标题,有些人可能想知道他们是否可以将该命名空间与WPF 应用程序一起使用——他们可以。

代码如下:

var file = File.ReadAllBytes(pdfFilePath);
var printQueue = LocalPrintServer.GetDefaultPrintQueue();

using (var job = printQueue.AddJob())
using (var stream = job.JobStream)

    stream.Write(file, 0, file.Length);

现在,这个命名空间必须与WPF 应用程序一起使用。它不适用于ASP.NETWindows Service。它不应该与Windows Forms 一起使用,因为它有System.Drawing.Printing。使用上述代码打印 PDF 时没有任何问题。

请注意,如果您的打印机不支持直接打印 PDF 文件,这将不起作用。

【讨论】:

【参考方案7】:

我尝试了很多方法,最适合我的方法是从命令行启动 SumatraPDF:

// Launch SumatraPDF Reader to print
String arguments = "-print-to-default -silent \"" + fileName + "\"";
System.Diagnostics.Process.Start("SumatraPDF.exe", arguments);

这样做有很多好处:

    SumatraPDF 比 Adob​​e Acrobat Reader 快得多。 UI 未加载。它只是打印。 您可以将 SumatraPDF 作为一个独立的应用程序使用,这样您就可以将它包含在您的应用程序中,这样您就可以使用自己的 pa。请注意,我没有阅读许可协议;你应该自己去看看。

【讨论】:

【参考方案8】:

我公司提供 Docotic.Pdf 库,可以render and print PDF documents。链接后面的文章包含有关以下主题的详细信息:

直接在 Windows 窗体或 WPF 应用程序中打印 PDF 通过中间图像打印 PDF 在图形上渲染 PDF

也有示例代码的链接。

我在公司工作,所以请阅读这篇文章并自己尝试建议的解决方案。

【讨论】:

【参考方案9】:

使用PrintDocument 类怎么样?

http://msdn.microsoft.com/en-us/library/system.drawing.printing.printdocument.aspx

您只需要传递您要打印的文件的文件名(基于示例)。

HTH

【讨论】:

正如我所描述的,这可以与 Drawing.Image 一起使用。它不适用于 .pdf。检查 pd_PrintPage(object sender, PrintPageEventArgs ev) 事件。 .txt 文件中的每一行都转换为打印输出。 请参阅daniweb.com/software-development/csharp/threads/90272/… 以获得可能的解决方案。【参考方案10】:
        Process proc = new Process();
        proc.StartInfo.FileName = @"C:\Program Files\Adobe\Acrobat 7.0\Reader\AcroRd32.exe";
        proc.StartInfo.Arguments = @"/p /h C:\Documents and Settings\brendal\Desktop\Test.pdf";
        proc.StartInfo.UseShellExecute = false;
        proc.StartInfo.CreateNoWindow = true;
        proc.Start();

        for (int i = 0; i < 5; i++)
        
            if (!proc.HasExited)
            
                proc.Refresh();
                Thread.Sleep(2000);
            
            else
                break;
        
        if (!proc.HasExited)
        
            proc.CloseMainWindow();
        

【讨论】:

【参考方案11】:

如果您对完全符合您要求的商业解决方案感兴趣,那么有很多选择。我的公司在名为 Debenu Quick PDF Library 的开发人员工具包中提供了其中一个选项。

这是一个代码示例(关键函数是PrintOptions和PrintDocument):

/* Print a document  */

// Load a local sample file from the input folder

DPL.LoadFromFile("Test.pdf", "");

// Configure print options

iPrintOptions = DPL.PrintOptions(0, 0, "Printing Sample")

// Print the current document to the default 
// printing using the options as configured above.
// You can also specify the specific printer.

DPL.PrintDocument(DPL.GetDefaultPrinterName(), 1, 1, iPrintOptions);

【讨论】:

【参考方案12】:

截至July 2018,OP 仍然没有答案。没有免费的方法可以 1) 为 2) 闭源项目静默打印您的 pdf。

1) 您当然可以使用 Adob​​e Acrobat 或 Foxit Reader 等进程

2) 免费解决方案具有 GPL(GNU 通用公共许可证)。这意味着如果将软件提供给公司以外的任何人,即使是免费的,您也必须开放源代码。

正如 OP 所说,如果您可以将 PDF 转换为 Drawing.Image,则可以使用 .NET 方法打印它。遗憾的是,执行此操作的软件还需要付费或 GPL。

【讨论】:

以上是关于如何使用 C# 打印 PDF的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 Windows 10 附带的 Microsoft Print To PDF 打印机以编程方式打印到 PDF 文件而不提示 C# 中的文件名

在 C# 中打印 Pdf [关闭]

如何发送文件到网络打印机,并打印(使用C#)?

C# 打印PDF文档的10种方法

c#使用PdfiumViewer展示打印pdf文档

C#如何在PDF文件添加图片印章