使用System.Printing对象打印时Commit方法抛出NotSupportedException求助
解决System.Printing中Commit方法抛出NotSupportedException的问题
你遇到的问题其实是因为System.Printing命名空间更偏向Windows打印系统的底层交互,它不会像System.Drawing.Printing.PrintDocument那样自动封装"另存为PDF"的对话框逻辑。Microsoft Print to PDF作为虚拟打印机,需要你手动指定输出文件路径并配置打印参数,否则就会抛出无信息的NotSupportedException。
下面是具体的解决方案,既能用System.Printing的对象实现需求,又能弹出保存对话框生成指定内容的PDF:
核心思路
- 找到Windows内置的"Microsoft Print to PDF"虚拟打印队列
- 手动弹出保存对话框让用户选择PDF输出路径
- 配置PrintTicket明确输出类型为PDF并指定文件路径
- 用熟悉的绘图逻辑生成打印内容,通过System.Printing提交作业
完整代码示例
using System; using System.Drawing; using System.Printing; using System.Windows.Forms; using System.Windows; using System.Windows.Media; using System.Windows.Xps; public void GeneratePdfWithSystemPrinting() { // 1. 获取Microsoft Print to PDF打印队列 PrintQueue pdfPrintQueue = null; try { // 打印队列名称必须和系统中的一致,默认是"Microsoft Print to PDF" pdfPrintQueue = new PrintQueue(new PrintServer(), "Microsoft Print to PDF"); } catch (PrintSystemException) { MessageBox.Show("未找到Microsoft Print to PDF打印机,请先在Windows可选功能中启用它!"); return; } // 2. 弹出保存对话框选择输出路径 using (var saveDialog = new SaveFileDialog()) { saveDialog.Filter = "PDF文件 (*.pdf)|*.pdf"; saveDialog.FileName = $"Print_{DateTime.Now:yyyyMMddHHmmss}.pdf"; saveDialog.Title = "保存PDF文档"; if (saveDialog.ShowDialog() != DialogResult.OK) return; // 用户取消操作 // 3. 创建打印作业并配置关键参数 var printJob = pdfPrintQueue.AddJob("PDF打印任务"); var printTicket = printJob.PrintTicket; // 必须指定输出文件和类型,这是解决Commit异常的关键 printTicket.OutputFile = saveDialog.FileName; printTicket.OutputFileType = OutputFileType.Pdf; printJob.PrintTicket = printTicket; // 4. 绘制打印内容(这里用WPF的DrawingVisual,也可以替换为System.Drawing的逻辑) var visual = new DrawingVisual(); using (var drawingContext = visual.RenderOpen()) { var printText = $"Printing @ {DateTime.Now:yyyy-MM-dd HH:mm:ss}"; // 配置文本样式 var formattedText = new FormattedText( printText, System.Globalization.CultureInfo.CurrentCulture, FlowDirection.LeftToRight, new Typeface("Arial"), 12, Brushes.Black); drawingContext.DrawText(formattedText, new Point(20, 20)); // 页面左上角偏移20单位 } // 5. 写入内容并提交作业 try { var writer = XpsDocumentWriter.CreateXpsDocumentWriter(printJob); writer.Write(visual, printTicket); printJob.Commit(); // 现在不会抛出NotSupportedException了 MessageBox.Show($"PDF已成功保存到:{saveDialog.FileName}"); } catch (Exception ex) { MessageBox.Show($"生成PDF失败:{ex.Message}"); printJob.Cancel(); } } }
为什么之前会抛出异常?
你之前的代码大概率没有设置PrintTicket的OutputFile和OutputFileType属性:
- Microsoft Print to PDF作为虚拟打印机,本质是把打印内容转换为PDF文件,必须明确告诉它文件要存到哪里
System.Drawing.Printing.PrintDocument之所以能正常工作,是因为它封装了上层逻辑,会自动触发Windows的"另存为"对话框并处理路径配置,而System.Printing需要你手动完成这些步骤
额外注意事项
- 如果系统中没有Microsoft Print to PDF,可以在设置 > 应用 > 可选功能中添加它
- 若你更习惯用
System.Drawing的绘图逻辑,可以把PrintDocument的内容转换为XPS流后再写入打印作业 - 确保程序有足够的权限访问打印队列和写入目标文件路径
内容的提问来源于stack exchange,提问作者BanksySan




