在C#中如何为ProcessStartInfo传递纸盒编号参数?打印附件时指定纸盒?
嘿,我来帮你搞定这两个关于打印时指定纸盒的问题:
首先得明确:ProcessStartInfo本身并没有直接支持传递纸盒编号的属性,因为当你使用Verb="PrintTo"时,本质是调用系统默认的文件处理程序(比如打开PDF的Adobe Reader、打开Word的Microsoft Word)来完成打印操作,而不同程序接受的命令行参数差异很大。所以核心思路是针对你要打印的文件类型,调用对应程序的命令行参数来指定纸盒。
举几个常见场景的例子:
打印PDF文件(用Adobe Reader/Acrobat):
Adobe的命令行参数支持静默打印并指定打印机,若要指定纸盒,可直接调用Acrobat Reader的可执行文件,结合打印机的纸盒设置来实现:string pdfPath = @"C:\test.pdf"; string printerName = "你的打印机名称"; int trayNumber = 2; // 这里的编号要对应打印机实际纸盒ID,可在打印机属性中查看 ProcessStartInfo info = new ProcessStartInfo(@"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"); // /t 参数表示静默打印到指定打印机,若需精确指定纸盒,可先将目标纸盒设为打印机默认,再执行打印 info.Arguments = $"/t \"{pdfPath}\" \"{printerName}\""; info.CreateNoWindow = true; info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; info.UseShellExecute = true; System.Diagnostics.Process.Start(info);打印Word文档(用Microsoft Word):
Word的命令行参数支持/p快速打印,但要指定纸盒,更可靠的方式是通过Word COM对象设置打印选项,而非单纯依赖命令行参数——你可以在代码中实例化Word应用,打开文档后设置PrintOut方法的PaperBin参数为目标纸盒编号。
看你提供的代码,你是用Verb="PrintTo"调用系统默认程序打印,这种方式无法直接传递纸盒参数,因为PrintTo的Arguments仅支持打印机名称,没有预留纸盒参数的位置。有两种可行的解决方案:
方案一:直接调用对应文件类型的处理程序,传递纸盒参数
比如打印PDF时直接调用Adobe Reader,替换原来的PrintTo逻辑,这样就能通过程序的命令行参数间接指定纸盒:
void PrintProcess(string FullFilePath) { string printerName = cmbPrinter.Text; int targetTray = 2; // 替换为你的目标纸盒编号 // 优先尝试用Adobe Reader打印PDF(如果需要支持其他文件类型,可根据扩展名判断对应程序) string acroReaderPath = @"C:\Program Files (x86)\Adobe\Acrobat Reader DC\Reader\AcroRd32.exe"; if (File.Exists(acroReaderPath) && FullFilePath.EndsWith(".pdf", StringComparison.OrdinalIgnoreCase)) { ProcessStartInfo info = new ProcessStartInfo(acroReaderPath); // 先将目标纸盒设为打印机默认,再执行静默打印 info.Arguments = $"/t \"{FullFilePath}\" \"{printerName}\""; info.CreateNoWindow = true; info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; info.UseShellExecute = true; System.Diagnostics.Process.Start(info); } else { // fallback到默认的PrintTo方式(无法指定纸盒) ProcessStartInfo info = new ProcessStartInfo(FullFilePath); info.Arguments = $"\"{printerName}\""; info.CreateNoWindow = true; info.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden; info.UseShellExecute = true; info.Verb = "PrintTo"; System.Diagnostics.Process.Start(info); } }
方案二:使用Win32 API设置打印作业的纸盒参数
如果你需要通用适配所有文件类型,可以通过Win32 API直接操控打印作业,设置纸盒属性。核心是通过DEVMODE结构体的dmDefaultSource字段指定纸盒编号,示例代码片段(需引用System.Runtime.InteropServices):
[DllImport("winspool.Drv", EntryPoint = "OpenPrinterA", SetLastError = true, CharSet = CharSet.Ansi, ExactSpelling = true, CallingConvention = CallingConvention.StdCall)] public static extern bool OpenPrinter([MarshalAs(UnmanagedType.LPStr)] string szPrinter, out IntPtr hPrinter, IntPtr pd); // 其他Win32 API声明(如ClosePrinter, StartDocPrinter等)省略... void PrintWithSpecifiedTray(string filePath, string printerName, int trayNumber) { IntPtr hPrinter = IntPtr.Zero; if (OpenPrinter(printerName, out hPrinter, IntPtr.Zero)) { // 这里需进一步获取打印机的DEVMODE结构体,设置dmDefaultSource为对应纸盒编号 // dmDefaultSource的常量值:DMBIN_UPPER=1、DMBIN_LOWER=2、DMBIN_MIDDLE=3等,需匹配打印机实际纸盒 // 后续完成创建打印作业、发送文件内容、结束作业的逻辑 ClosePrinter(hPrinter); } }
注:纸盒编号对应的dmDefaultSource值需要和打印机实际匹配,可通过打印机属性或EnumForms API查询。
内容的提问来源于stack exchange,提问作者Sai

