C# 打印PDF的常用方法
这里先提供一个helper类的模板
1.使用默认程序打印
using System; using System.Collections.Generic; using System.Diagnostics; using System.Drawing.Printing; using System.IO; using System.Runtime.InteropServices; namespace PDF { public static class PrintHelper { #region 打印机操作核心方法 /// /// // 设置默认打印机 /// /// /// [DllImport("winspool.drv")] public static extern bool SetDefaultPrinter(String Name); /// /// 获取系统默认打印机名称 /// public static string DefaultPrinterName() { PrintDocument fPrintDocument = new PrintDocument(); return fPrintDocument.PrinterSettings.PrinterName; } /// /// 获取本机所有打印机列表 /// public static List GetLocalPrinters() { List fPrinters = new List(); fPrinters.Add(DefaultPrinterName()); foreach (string fPrinterName in PrinterSettings.InstalledPrinters) { if (!fPrinters.Contains(fPrinterName)) { fPrinters.Add(fPrinterName); } } return fPrinters; } /// /// 设置指定打印机为默认打印机 /// public static bool SetLocalPrinter(string defaultPrinter) { foreach (string item in GetLocalPrinters()) { if (item.Contains(defaultPrinter)) { return SetDefaultPrinter(item); } } return false; } #endregion /// /// 打印 /// 通过系统关联程序打印文件 /// 需注意的是,这种方式依赖于文件类型的默认关联程序 /// public static void PrintByDefaultProcess(string LocalPath) { Process p = new Process(); ProcessStartInfo startInfo = new ProcessStartInfo { CreateNoWindow = true, WindowStyle = ProcessWindowStyle.Hidden, UseShellExecute = true, FileName = LocalPath, Verb = "print", // 它会调用与文件类型关联的默认应用程序来执行打印文件,如Adobe Reader或者word或图片查看器或其他PDF阅读器进行打印 Arguments = $"/p /h \"{LocalPath}\" \"{DefaultPrinterName()}\"", //WorkingDirectory = Path.GetDirectoryName(Application.ExecutablePath) // 设置工作目录为应用程序启动目录 }; p.StartInfo = startInfo; p.Start(); p.WaitForExit(5); // 等待5秒钟,确保打印任务已提交 } } }
需要注意的是,它虽然是一种简单且常用的方法。但这种方法依赖于系统关联的默认应用程序来处理打印任务,适用于大多数情况,但存在一些限制和潜在问题。如pdf后缀没有关联默认程序会报错。
所以我一般不会使用这种方式。
下面会罗列其他的方法和优缺点
2.使用命令行工具(如 Adobe Reader 的 /t 参数)
public static void PrintWithAdobeCommandLine(string filePath, string printerName) { string adobePath = @"C:\Program Files\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"; Process.Start(adobePath, $"/t \"{filePath}\" \"{printerName}\""); }
优点:绕过默认应用程序,强制使用 Adobe Reader。
缺点:需硬编码 Adobe 路径,可能因版本或安装位置不同失效。
3.直接调用 Adobe Acrobat 的 COM 接口
如果系统中安装了 Adobe Acrobat Pro,可以通过 COM 对象直接控制打印:
using Adobe.Acrobat; public static void PrintWithAdobePdf(string filePath) { Acrobat.AcroApp app = new Acrobat.AcroApp(); Acrobat.AcroAVDoc avDoc = new Acrobat.AcroAVDoc(); if (avDoc.Open(filePath, "")) { Acrobat.AcroPDDoc pdDoc = (Acrobat.AcroPDDoc)avDoc.GetPDDoc(); pdDoc.PrintPages(0, 0, 0, 0, 0, 0, 0); // 参数需根据需求调整 avDoc.Close(true); } app.Exit(); }
优点:直接控制 Adobe 软件,可靠性高。
缺点:依赖 Adobe Acrobat Pro,非免费版;需处理 COM 引用和资源释放。
4. 使用 .NET 的 PrintDocument 类
结合 System.Drawing 处理 PDF(需将 PDF 渲染为图像):
public static void PrintPdfAsImage(string filePath) { using (var document = PdfDocument.Load(filePath)) // 需要 PdfiumViewer 或其他库 { var printDoc = new System.Drawing.Printing.PrintDocument(); printDoc.PrintPage += (sender, e) => { e.Graphics.DrawImage(document.RenderToImage(), e.MarginBounds); e.HasMorePages = false; }; printDoc.Print(); } }
**优点:纯 .NET 实现。
缺点:**渲染质量依赖库,可能丢失文本选中等特性。
5. 使用 DEVExpress的PdfView打印
基本打印代码
using DevExpress.XtraPrinting; using DevExpress.XtraPrinting.Preview; private void PrintPdf() { // 检查 PdfViewer 是否已加载文档 if (pdfViewer1.Document == null) { MessageBox.Show("请先加载 PDF 文件!"); return; } // 调用 Print 方法(弹出系统打印对话框) pdfViewer1.Print(); }
高级打印配置(自定义打印机/页边距)
private void PrintPdfWithSettings() { if (pdfViewer1.Document == null) return; // 创建打印参数对象 var printParams = new PrinterSettings { PrinterName = "Your_Printer_Name", // 指定打印机名称(需与系统一致) Copies = 2, // 打印份数 FromPage = 1, // 起始页 ToPage = 3 // 结束页(设置为 0 表示全部) }; // 创建打印文档对象 var printDocument = pdfViewer1.CreatePrintDocument(); // 配置打印事件(可选) printDocument.PrintPage += (s, e) => { // 可在此处自定义打印逻辑(例如添加水印) e.HasMorePages = false; // 标记是否还有后续页面 }; // 应用打印参数并执行打印 printDocument.PrinterSettings = printParams; printDocument.Print(); // 静默打印(不弹出对话框) }
打印预览
private void PreviewBeforePrint() { if (pdfViewer1.Document == null) return; // 创建打印预览窗体 var printPreviewForm = new PrintPreviewForm(pdfViewer1); printPreviewForm.ShowDialog(); }
完整示例
private void SafePrintPdf() { try { if (pdfViewer1.Document == null) { MessageBox.Show("未加载 PDF 文件!"); return; } var printDialog = new PrintDialog { Document = pdfViewer1.CreatePrintDocument(), AllowCurrentPage = true, // 允许选择当前页 AllowSomePages = true }; if (printDialog.ShowDialog() == DialogResult.OK) { printDialog.Document.Print(); } } catch (Exception ex) { MessageBox.Show($"打印失败: {ex.Message}"); } }
以下是常见的主流三方dll打印,推荐
一、iTextSharp(免费/商业)
特点:
免费版:仅限非商业用途,功能受限。
商业版:需购买许可证,支持完整功能。
需配合其他库:iText 本身不直接提供打印功能,需结合 System.Drawing 或 Ghostscript 渲染后打印。
示例代码(静默打印):
using iTextSharp.text.pdf; using System.Diagnostics; public static void PrintWithITextSharp(string filePath) { try { // 使用 Ghostscript 渲染 PDF 为图像(需安装 Ghostscript) Process process = new Process(); process.StartInfo.FileName = "gswin64c.exe"; // Ghostscript 路径 process.StartInfo.Arguments = $"-dBATCH -dNOPAUSE -sDEVICE=mswinpr2 -sOutputFile=\"%printer%{GetDefaultPrinter()}\" \"{filePath}\""; process.StartInfo.UseShellExecute = false; process.StartInfo.CreateNoWindow = true; process.Start(); process.WaitForExit(); } catch (Exception ex) { throw new Exception($"打印失败: {ex.Message}"); } } // 获取默认打印机名称 private static string GetDefaultPrinter() { return System.Drawing.Printing.PrinterSettings.InstalledPrinters.Cast().FirstOrDefault(p => p.ToLower().Contains("pdf")); }
需要注意的是:这里为啥不用System.Drawing,因为如下
System.Drawing 主要用于 生成图形内容(如绘制线条、文本、图像),而不是解析 PDF 文件。如果要打印 PDF,需要先将 PDF 渲染为位图或矢量图像,再通过 System.Drawing.Printing.PrintDocument 发送到打印机。但这种方式会导致:
分辨率问题:PDF 的矢量内容会被栅格化为位图,放大后可能模糊。
性能问题:大文件渲染耗时,内存占用高。
功能缺失:无法保留 PDF 的文本可编辑性、书签等元数据。
以下是使用System.Drawing.Printing.PrintDocument 的方式,如果 PDF 是单页且内容简单,可以用 System.Drawing 渲染第一页为图像后打印
using System.Drawing; using System.Drawing.Imaging; using System.Drawing.Printing; public static void PrintPdfAsImage(string filePath) { using (var image = RenderPdfToImage(filePath)) // 需自行实现 PDF 到图像的渲染 { var printDoc = new PrintDocument(); printDoc.PrintPage += (s, e) => { e.Graphics.DrawImage(image, e.MarginBounds); e.HasMorePages = false; }; printDoc.Print(); } } // 注意:需使用第三方库(如 PdfiumViewer)实现 RenderPdfToImage
二、PdfiumViewer(免费开源)
特点:
基于 Google 的 Pdfium 引擎,渲染性能高。
直接支持 PDF 打印,无需额外依赖。
支持静默打印、自定义页码范围。
优点:
无需额外依赖,API 简洁。
支持 PDF 元数据、书签等高级操作。
示例代码
using PdfiumViewer; public static void PrintWithPdfiumViewer(string filePath, string printerName = null) { using (var document = PdfDocument.Load(filePath)) { var printDialog = new System.Windows.Forms.PrintDialog { PrinterSettings = { PrinterName = printerName } // 可选指定打印机 }; if (printDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK) { document.Print(printDialog.PrinterSettings); } } }
高级用法(静默打印):
public static void SilentPrint(string filePath) { using (var document = PdfDocument.Load(filePath)) { var printerSettings = new System.Drawing.Printing.PrinterSettings { PrinterName = "Your_Printer_Name", Copies = 2 }; document.Print(printerSettings); } }
三、Spire.PDF(商业授权)
特点:
商业库,需购买许可证(免费版有水印)。
提供完整的 PDF 操作 API,包括打印、转换、加密等。
支持静默打印、自定义页边距、多线程打印。
注意事项:
免费版会在输出文件添加评估水印。
需在项目中引用 Spire.PDF NuGet 包。
示例代码
using Spire.Pdf; using Spire.Pdf.Graphics; public static void PrintWithSpirePdf(string filePath) { PdfDocument doc = new PdfDocument(); doc.LoadFromFile(filePath); // 配置打印参数 PdfPrintOptions options = new PdfPrintOptions { PrinterName = "Your_Printer_Name", Copies = 1, Range = PdfPrintRange.AllPages }; // 静默打印(无对话框) doc.Print(options); }
高级功能(添加水印后打印):
public static void PrintWithWatermark(string filePath) { PdfDocument doc = new PdfDocument(); doc.LoadFromFile(filePath); foreach (PdfPageBase page in doc.Pages) { PdfFont font = new PdfFont(PdfFontFamily.Helvetica, 50); PdfBrush brush = PdfBrushes.LightGray; page.Canvas.DrawString("CONFIDENTIAL", font, brush, new PointF(0, 0)); } doc.SaveToFile("Watermarked.pdf"); doc.Close(); // 打印带水印的文件 PrintWithSpirePdf("Watermarked.pdf"); }
推荐场景
推荐 PdfiumViewer:免费、高性能,适合大多数场景。
商业项目选 Spire.PDF:功能全面,省去外部依赖。
避免 System.Drawing 直接打印 PDF:除非是单页简单内容。
已有 Ghostscript 环境 → iTextSharp(需额外配置)
大文件打印时,优先使用 PdfiumViewer 或 Spire.PDF(内存占用更低)。
批量打印时,关闭自动刷新(如 Spire.Pdf 的 Options.NoSaveAfterPrint)。