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

C# WPF实现无用户交互打印到文件的问题咨询

问题复现

你当前使用的打印逻辑代码如下:

Canvas c = GetMyCanvas();
PrintDialog p = new PrintDialog();
PrintQueue printQueue = GetPrintQueues("Printer1"); //this printer is configured as Print To File
PrintTicket printTicket = GetPrintTicket(printQueue);
        
//Create a fixed Document and Print the document
FixedDocument fixedDoc = new FixedDocument();
PageContent pageContent = new PageContent();
FixedPage fixedPage = new FixedPage();
fixedPage.Height = 11.69 * 96;
fixedPage.Width = 8.27 * 96;

fixedPage.Children.Add(c);
((System.Windows.Markup.IAddChild)pageContent).AddChild(fixedPage);
fixedDoc.Pages.Add(pageContent);

XpsDocument xpsDoc = new XpsDocument(".\xpsDocTest.xps", FileAccess.Write);
XpsDocumentWriter xWriter = XpsDocument.CreateXpsDocumentWriter(xpsDoc);
xWriter.Write(fixedDoc, printTicket);
xpsDoc.Close();

printQueue.AddJob("prova", ".\xpsDocTest.xps", false);

当前遇到的问题:调用AddJob函数时会弹出「另存输出文件」对话框,需要用户手动指定文件名,不符合无人工干预的业务需求,需要兼容包括打印到文件类在内的所有打印机类型。
微软官方给出的弹窗原因是:

若要避免向默认队列添加打印作业时弹出「另存输出文件」对话框,请确保默认打印机不是Microsoft XPS Document Writer、Microsoft Print to PDF或其他打印到文件类选项。


解决方案

方法1:修改打印队列端口配置,提前指定输出路径(兼容现有代码逻辑)

打印到文件类打印机的弹窗本质是端口未指定默认输出路径触发的交互逻辑,你可以在调用AddJob前,通过打印系统API修改对应打印机的端口输出路径,即可完全规避弹窗,该方法需要程序以管理员权限运行。
示例修改代码:

// 假设printQueue是你已经获取到的打印到文件类打印机队列
using (PrintServer printServer = new PrintServer())
{
    PrintQueue queue = printServer.GetPrintQueue(printQueue.Name);
    queue.DefaultPrintTicket.OutputFileName = @"C:\目标路径\输出文件.xps";
    // 针对PDF打印机同理,修改后缀为pdf即可
    queue.Commit();
}
// 再调用你原有的AddJob逻辑,不会再弹出对话框
printQueue.AddJob("prova", ".\xpsDocTest.xps", false);

方法2:替换AddJob调用,使用Win32底层打印API规避弹窗

如果不想申请管理员权限修改打印机配置,可以直接调用Win32的StartDocPrinter系列API,在DOC_INFO_1结构体中直接指定输出文件路径,兼容性更强,不会触发交互弹窗。
核心逻辑示例:

// 先声明Win32 API
[DllImport("winspool.Drv", EntryPoint = "StartDocPrinterW", SetLastError = true, CharSet = CharSet.Unicode, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)]
public static extern bool StartDocPrinter(IntPtr hPrinter, int level, [In, MarshalAs(UnmanagedType.LPStruct)] DOC_INFO_1 pDocInfo);

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public class DOC_INFO_1
{
    [MarshalAs(UnmanagedType.LPWStr)] public string pDocName;
    [MarshalAs(UnmanagedType.LPWStr)] public string pOutputFile; // 直接在这里指定输出路径即可
    [MarshalAs(UnmanagedType.LPWStr)] public string pDataType;
}

调用时直接在pOutputFile字段传入你要生成的文件完整路径,打印任务会直接输出到对应路径,不会弹出对话框。

方法3:绕过打印队列直接生成目标文件

如果你的业务需求最终是要得到PDF/XPS格式的输出文件,不需要真的提交到打印队列,可以直接用对应类库生成文件,完全规避打印相关的交互逻辑:

  • 生成XPS可以直接复用你现有XpsDocument的写入逻辑,不需要调用AddJob提交打印任务,生成的本地文件即可直接使用
  • 生成PDF可以用PdfSharp、iText等开源库,将你生成的FixedPage内容转换为PDF格式保存,全程不需要调用打印相关API,自然不会触发弹窗。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 20:24:04