如何通过C#代码直接打印文件(如PDF)?支持无对话框及参数配置
作为C#新手,想实现无弹窗直接打印PDF还能自定义打印参数?完全没问题!我刚学C#的时候也纠结过这个,下面给你几个亲测有效的方案,从原生.NET结合轻量库,到直接调用Windows API,再到省心的第三方工具,一步步来:
方案1:用PdfiumViewer(轻量开源)+ .NET PrintDocument
.NET原生没有直接处理PDF打印的类,所以我们可以用PdfiumViewer这个开源库(MIT协议,免费商用)来渲染PDF,再结合PrintDocument实现无对话框打印,还能指定打印机和份数。
步骤:
- 先在NuGet包管理器里安装
PdfiumViewer; - 用下面的代码实现:
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
相关产品推荐
相关产品推荐

