C# 打印PDF的常用方法

这里先提供一个helper类的模板
1.使用默认程序打印

csharp 复制代码
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 打印机操作核心方法

        /// <summary>
        /// // 设置默认打印机
        /// </summary>
        /// <param name="Name"></param>
        /// <returns></returns>
        [DllImport("winspool.drv")]
        public static extern bool SetDefaultPrinter(String Name);

        /// <summary>
        /// 获取系统默认打印机名称
        /// </summary>
        public static string DefaultPrinterName()
        {
            PrintDocument fPrintDocument = new PrintDocument();
            return fPrintDocument.PrinterSettings.PrinterName;
        }

        /// <summary>
        /// 获取本机所有打印机列表
        /// </summary>
        public static List<string> GetLocalPrinters()
        {
            List<string> fPrinters = new List<string>();
            fPrinters.Add(DefaultPrinterName());

            foreach (string fPrinterName in PrinterSettings.InstalledPrinters)
            {
                if (!fPrinters.Contains(fPrinterName))
                {
                    fPrinters.Add(fPrinterName);
                }
            }
            return fPrinters;
        }

        /// <summary>
        /// 设置指定打印机为默认打印机
        /// </summary>
        public static bool SetLocalPrinter(string defaultPrinter)
        {
            foreach (string item in GetLocalPrinters())
            {
                if (item.Contains(defaultPrinter))
                {
                    return SetDefaultPrinter(item);
                }
            }
            return false;
        }

        #endregion

        /// <summary>
        /// 打印
        /// 通过系统关联程序打印文件
        /// 需注意的是,这种方式依赖于文件类型的默认关联程序
        /// </summary>
        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 参数)​

csharp 复制代码
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 对象直接控制打印:

csharp 复制代码
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 渲染为图像):

csharp 复制代码
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打印 ​

基本打印代码

csharp 复制代码
using DevExpress.XtraPrinting;
using DevExpress.XtraPrinting.Preview;

private void PrintPdf()
{
    // 检查 PdfViewer 是否已加载文档
    if (pdfViewer1.Document == null)
    {
        MessageBox.Show("请先加载 PDF 文件!");
        return;
    }

    // 调用 Print 方法(弹出系统打印对话框)
    pdfViewer1.Print();
}

高级打印配置(自定义打印机/页边距)​

csharp 复制代码
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(); // 静默打印(不弹出对话框)
}

打印预览

csharp 复制代码
private void PreviewBeforePrint()
{
    if (pdfViewer1.Document == null) return;

    // 创建打印预览窗体
    var printPreviewForm = new PrintPreviewForm(pdfViewer1);
    printPreviewForm.ShowDialog();
}

完整示例

csharp 复制代码
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 渲染后打印。

示例代码(静默打印):

csharp 复制代码
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<string>().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 渲染第一页为图像后打印

csharp 复制代码
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 元数据、书签等高级操作。

示例代码

csharp 复制代码
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);
        }
    }
}

高级用法(静默打印):

csharp 复制代码
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 包。

示例代码

csharp 复制代码
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);
}

高级功能(添加水印后打印):

csharp 复制代码
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)。

相关推荐
纪元A梦4 小时前
Acrobat DC v25.001 最新专业版已破,像word一样编辑PDF!
pdf·办公软件·windows软件·acrobat pro dc·pdf软件·acrobat 底层
江湖有缘4 小时前
【Docker项目实战篇】Docker部署PDF查看器PdfDing
docker·eureka·pdf
shangjg35 小时前
Kafka 如何保证顺序消费
c#·linq
FuckPatience5 小时前
C# 关于闭包与多线程结合使用
c#
半青年6 小时前
IEC61850规约客户端软件开发实战(第二章)
java·c++·qt·网络协议·c#·信息与通信·iec61850
TA远方6 小时前
【C#】一个简单的http服务器项目开发过程详解
服务器·http·c#·wpf·web·winform·console
CodeCraft Studio6 小时前
国产化Excel处理组件Spire.XLS教程:如何使用 C# 将 Excel(XLS 或 XLSX)文件转换为 PDF
pdf·c#·excel
招财进宝。。6 小时前
c# 获取电脑 分辨率 及 DPI 设置
开发语言·c#·电脑
zybsjn8 小时前
后端项目中静态文案国际化语言包构建选型
java·后端·c#
vvilkim8 小时前
深入理解C#异步编程:原理、实践与最佳方案
服务器·开发语言·c#