You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过C#代码直接打印文件(如PDF)?支持无对话框及参数配置

作为C#新手,想实现无弹窗直接打印PDF还能自定义打印参数?完全没问题!我刚学C#的时候也纠结过这个,下面给你几个亲测有效的方案,从原生.NET结合轻量库,到直接调用Windows API,再到省心的第三方工具,一步步来:

方案1:用PdfiumViewer(轻量开源)+ .NET PrintDocument

.NET原生没有直接处理PDF打印的类,所以我们可以用PdfiumViewer这个开源库(MIT协议,免费商用)来渲染PDF,再结合PrintDocument实现无对话框打印,还能指定打印机和份数。

步骤:

  1. 先在NuGet包管理器里安装PdfiumViewer;
  2. 用下面的代码实现:
using PdfiumViewer;
using System.Drawing.Printing;

public static void PrintPdfSilently(string pdfPath, string printerName, int copies)
{
    // 加载PDF文档
    using (var pdfDocument = PdfDocument.Load(pdfPath))
    // 创建可打印的文档对象
    using (var printDocument = pdfDocument.CreatePrintDocument())
    {
        // 指定目标打印机(可以从PrinterSettings.InstalledPrinters里获取已安装的打印机名)
        printDocument.PrinterSettings.PrinterName = printerName;
        // 设置打印份数
        printDocument.PrinterSettings.Copies = (short)copies;
        // 禁用打印对话框,直接发送任务
        printDocument.PrintController = new StandardPrintController();
        
        try
        {
            printDocument.Print();
            Console.WriteLine("打印任务已成功发送!");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"打印出错啦:{ex.Message}");
        }
    }
}
方案2:直接调用Windows API(ShellExecuteEx)

如果不想引入第三方库,可以直接调用Windows的ShellExecuteEx API,让系统关联的PDF阅读器(比如Edge、Adobe Reader)后台打印,不需要自己处理PDF渲染。

代码示例:

using System;
using System.Runtime.InteropServices;

public static class PrintHelper
{
    // 定义Windows API需要的结构体
    [StructLayout(LayoutKind.Sequential)]
    private struct SHELLEXECUTEINFO
    {
        public int cbSize;
        public uint fMask;
        public IntPtr hwnd;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpVerb;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpFile;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpParameters;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpDirectory;
        public int nShow;
        public IntPtr hInstApp;
        public IntPtr lpIDList;
        [MarshalAs(UnmanagedType.LPWStr)]
        public string lpClass;
        public IntPtr hkeyClass;
        public uint dwHotKey;
        public IntPtr hIcon;
        public IntPtr hProcess;
    }

    // 导入ShellExecuteEx函数
    [DllImport("shell32.dll", SetLastError = true)]
    private static extern bool ShellExecuteEx(ref SHELLEXECUTEINFO lpExecInfo);

    private const int SW_HIDE = 0;
    private const uint SEE_MASK_NOCLOSEPROCESS = 0x00000040;

    public static bool PrintPdfWithShell(string pdfPath, string printerName, int copies)
    {
        var execInfo = new SHELLEXECUTEINFO();
        execInfo.cbSize = Marshal.SizeOf(execInfo);
        execInfo.fMask = SEE_MASK_NOCLOSEPROCESS;
        execInfo.hwnd = IntPtr.Zero;
        execInfo.lpVerb = "printto"; // 指定用"打印到"命令,能自定义打印机
        execInfo.lpFile = pdfPath;
        // 参数格式:"打印机名" "驱动名" "端口名" 份数(驱动和端口留空即可)
        execInfo.lpParameters = $"\"{printerName}\" \"\" \"\" {copies}";
        execInfo.nShow = SW_HIDE; // 隐藏阅读器窗口,无弹窗
        execInfo.lpDirectory = null;

        bool result = ShellExecuteEx(ref execInfo);
        if (!result)
        {
            int errorCode = Marshal.GetLastWin32Error();
            Console.WriteLine($"调用系统打印失败,错误码:{errorCode}");
        }
        return result;
    }
}

注意:

这个方案依赖系统里已安装的PDF阅读器(必须能关联PDF文件),如果用户电脑没装的话会失败。

方案3:用第三方PDF库(比如iText7)

如果需要更复杂的PDF处理(比如打印前修改内容),可以用iText7,不过要注意:免费版是AGPL协议,商用需要购买许可证。

简单示例(仅打印文本,完整渲染建议用PdfiumViewer):

using iText.Kernel.Pdf;
using iText.Kernel.Pdf.Canvas.Parser.Listener;
using System.Drawing.Printing;
using System.Drawing;

public static void PrintPdfWithiText(string pdfPath, string printerName, int copies)
{
    using (PdfDocument pdfDoc = new PdfDocument(new PdfReader(pdfPath)))
    {
        PrintDocument printDoc = new PrintDocument();
        printDoc.PrinterSettings.PrinterName = printerName;
        printDoc.PrinterSettings.Copies = (short)copies;
        printDoc.PrintController = new StandardPrintController();

        // 绑定打印页面事件
        printDoc.PrintPage += (sender, e) =>
        {
            // 获取当前要打印的PDF页码(注意.NET的PageNumber从0开始,iText从1开始)
            int pdfPageNum = e.PageSettings.PrintableArea.PageNumber + 1;
            if (pdfPageNum > pdfDoc.GetNumberOfPages()) return;

            // 提取PDF页面文本并打印(如果要完整渲染页面,需要额外处理)
            var textStrategy = new LocationTextExtractionStrategy();
            string pageText = iText.Kernel.Pdf.Canvas.Parser.PdfTextExtractor.GetTextFromPage(pdfDoc.GetPage(pdfPageNum), textStrategy);
            e.Graphics.DrawString(pageText, new Font("Arial", 10), Brushes.Black, new PointF(10, 10));
        };

        try
        {
            printDoc.Print();
            Console.WriteLine("打印完成!");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"打印出错:{ex.Message}");
        }
    }
}
额外小提示:
  • 可以用PrinterSettings.InstalledPrinters遍历系统里所有已安装的打印机,确保你指定的打印机名称正确;
  • 测试前先确认打印机处于正常状态(联机、有纸);
  • 如果是Web应用,要注意权限问题,服务器端打印需要打印机在服务器上可用。

内容的提问来源于stack exchange,提问作者glw7v8

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:25:12