C# 打印PDF的常用方法

news2025/5/31 22:15:39

这里先提供一个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 打印机操作核心方法

        /// <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 参数)​

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<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 渲染第一页为图像后打印

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)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2391940.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

若依微服务的定制化服务

复制依赖 复制依赖 复制system服务的bootstrap.yml文件&#xff0c;修改port和name 在nacos复制一个新的nacos配置&#xff0c;修改对应的nacos的配置 &#xff0c;可能不需要修改&#xff0c;看情况。 网关修改 注意curd的事项&#xff0c;模块名称的修改

Axios 如何通过配置实现通过接口请求下载文件

前言 今天&#xff0c;我写了 《Nodejs 实现 Mysql 数据库的全量备份的代码演示》 和 《NodeJS 基于 Koa, 开发一个读取文件&#xff0c;并返回给客户端文件下载》 两篇文章。在这两篇文章中&#xff0c;我实现了数据库的备份&#xff0c;和提供数据库下载等接口。 但是&…

20250529-C#知识:运算符重载

C#知识&#xff1a;运算符重载 运算符重载能够让我们像值类型数据那样使用运算符对类或结构体进行运算&#xff0c;并且能够自定义运算逻辑。 1、运算符重载及完整代码示例 作用是让自定义的类或者结构体能够使用运算符运算符重载一定是public static的可以把运算符看成一个函…

如何在WordPress网站中添加相册/画廊

在 WordPress 网站上添加相册可以让您展示许多照片。无论您是在寻找标准的网格相册画廊还是独特的瀑布流相册画廊体验&#xff0c;学习如何在 WordPress 网站上添加相册总是一个好主意。在本教程中&#xff0c;我们将介绍两种为 WordPress 网站添加相册的方法&#xff1a;使用区…

Codeforces Round 1025 (Div. 2)

Problem - A - Codeforces 查有没有人说谎&#xff0c;有一个必错的情况&#xff1a; 两个人都说输了&#xff0c;必有人撒谎&#xff0c;还有就是所有人都赢了&#xff0c;也是撒谎 来看代码&#xff1a; #include <iostream> #include <vector> using namespa…

Ubuntu20.04操作系统ssh开启oot账户登录

文章目录 1 前提2 设置root密码3 允许ssh登录root账户3.1 编辑配置文件3.2 重启ssh服务 4 安全注意事项 1 前提 ssh可以使用普通用户正常登录。 2 设置root密码 打开终端&#xff0c;设置密码 sudo passwd root # 设置root密码3 允许ssh登录root账户 3.1 编辑配置文件 su…

类欧几里得算法(floor_sum)

文章目录 普通floor_sum洛谷P5170 【模板】类欧几里得算法 万能欧几里得算法求 ∑ i 1 n A i B ⌊ a i b c ⌋ \sum_{i1}^{n}A^iB^{\lfloor \frac{aib}{c} \rfloor} ∑i1n​AiB⌊caib​⌋求 ∑ i 0 n ⌊ a i b c ⌋ \sum_{i0}^n \lfloor\frac{aib}{c}\rfloor ∑i0n​⌊caib…

每日Prompt:卵石拼画

提示词 世界卵石拼画大师杰作&#xff0c;极简风格&#xff0c;贾斯汀.贝特曼的风格&#xff0c;彩色的鹅卵石&#xff0c;斑马头像&#xff0c;鹅卵石拼画&#xff0c;马卡龙浅紫色背景&#xff0c;自然与艺术的结合&#xff0c;新兴的艺术创作形式&#xff0c;石头拼贴画&am…

硬件服务器基础

1、硬件服务器基础 2、服务器后面板 3、组件 3.1 CPU 3.2 内存 3.3 硬盘 3.4 风扇 4、服务器品牌 4.1 配置 4.2 CPU 架构 4.2.1 CPU 命名规则 4.2.2 服务器 CPU 和家用 CPU 的区别 4.2.3 CPU 在主板的位置 4.2.4 常见 CPU 安装方式 4.3 内存中组件 4.3.1 内存的分类 4.3.1.1 …

TRS收益互换平台开发实践:从需求分析到系统实现

一、TRS业务概述 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;允许投资者通过支付固定或浮动利息&#xff0c;换取标的资产&#xff08;如股票、指数&#xff09;的收益权。典型应用场景包括&#xff1a; ​​跨境投资​​&#xff…

测试Bug篇

本节概要&#xff1a; 软件测试的生命周期 bug的概念 buh要素 bug等级 bug生命周期 对于bug的定级与开发发生冲突如何解决 一、 软件测试的⽣命周期 软件测试贯穿于软件的整个生命周期&#xff0c;针对这句话我们⼀起来看⼀下软件测试是如何贯穿软件的整个生命周期。 软…

【Linux系统移植】Cortex-A8 Linux系统移植(超详细)

目录 前言 一、ARM开发板ARM简介RISC和CISCARM产品分布核心板S5pv210 SOC嵌入式系统开发方式 二、嵌入式系统组成为什么要系统移植内核移植框图 三、嵌入式开发环境搭建搭建开发环境总流程设置ubuntu与windows共享目录修改用户为root用户安装NFS服务器安装tftp服务器安装交叉编…

第十五届蓝桥杯大赛软件赛国赛Python 大学 C 组试做【本期题单: 设置密码、栈】

早上好啊大伙&#xff0c;这一期依旧是蓝桥杯备赛刷题的记录。 本期题单&#xff1a;设置密码、栈 前言 前段时间准备省赛&#xff0c;运气好进国赛了。所以就开始准备6月份的国赛。但是近期还有别的比赛要准备&#xff0c;所以刷题的速度比较慢&#xff0c;可能每一期就会有一…

报错SvelteKitError: Not found: /.well-known/appspecific/com.chrome.devtools.json

报错信息 SvelteKitError: Not found: /.well-known/appspecific/com.chrome.devtools.json 解决方案一 更新所有依赖 npm update解决方案二&#xff08;不一定成功&#xff09; src\lib\hooks.server.ts&#xff0c;每次请求服务器时执行 import type { Handle } from &…

word添加页眉

问题一&#xff1a; 为word文档添加页眉。 方法&#xff1a; 1、在要添加页眉的第一页页面顶端双击页眉区域&#xff0c;如果添加页眉页上面还有其他页或者与上一页添加页眉内容不同&#xff0c;记得取消“链接到前一节”&#xff08;点击使其上面没有灰色即可&#xff09;&…

2025推客系统小程序开发:独立部署源码交付,高性价比裂变增长引擎

在私域流量争夺白热化的今天&#xff0c;源码独立部署的推客系统小程序已成为企业构建自主分销体系、降低获客成本的核心利器。基于成熟案例与技术沉淀&#xff0c;我们提供安全可控、高性价比的一站式解决方案&#xff0c;助力企业快速搭建专属推客生态&#xff0c;实现长效增…

CentOS 7.0重置root密码

文章目录 版本&#xff1a;CentOS 7.0内核版本&#xff1a;CentOS Linux, with Linux 3.10.0-123.el7.x86_64 服务器重启后&#xff0c;等待进入上述页面&#xff0c;按⬆⬇键&#xff0c;中断正常启动。在此页面按E&#xff0c;进入编辑模式 继续按⬇&#xff0c;找到linux16…

YOLOV11改进策略【最新注意力机制】CVPR2025局部区域注意力机制LRSA-增强局部区域特征之间的交互

1.1网络结构 1.2 添加过程 1.2.1 核心代码 import torch import torch.nn as nn import torch.nn.functional as F from einops import rearrangedef patch_divide(x, step, ps):"""Crop image into patches.Args:x (Tensor): Input feature map of shape(b, …

DAY33 简单神经网络

你需要自行了解下MLP的概念。 你需要知道 梯度下降的思想激活函数的作用损失函数的作用优化器神经网络的概念 神经网络由于内部比较灵活&#xff0c;所以封装的比较浅&#xff0c;可以对模型做非常多的改进&#xff0c;而不像机器学习三行代码固定。 1. 神经网络的概念 (Th…

OBOO鸥柏丨2025年鸿蒙生态+国产操作系统触摸屏查询一体机核心股

在信创产业蓬勃发展的当下&#xff0c;OBOO鸥柏积极响应纯国产化号召&#xff0c;推出基于华为鸿蒙HarmonyOS操作系统的触摸屏查询一体机及室内外场景广告液晶显示屏一体机上市&#xff0c;OBOO鸥柏品牌旗下显示产品均采用国产芯片&#xff0c;接入终端控制端需支持安卓Windows…