C#中如何防止ProcessStartInfo的print谓词执行时弹出窗口?
问题
尝试使用以下代码打印应用程序生成的文件:
var psi = new ProcessStartInfo("Temp.txt"); psi.UseShellExecute = true; psi.Verb = "print"; psi.CreateNoWindow = true; var process = System.Diagnostics.Process.Start(psi);
上述代码功能正常,可以按预期将文件发送至打印机,但执行过程中会弹出记事本窗口,持续1秒左右自动关闭。由于应用设计为后台运行,这类弹窗会对用户造成极大干扰。
此前尝试在启动进程的代码前添加psi.WindowStyle = ProcessWindowStyle.Hidden;(原代码笔误写为pi变量),仅能起到微弱改善效果,仍然会出现短暂的小型弹窗,会打断用户当前正在使用的全屏应用。
原因
调用txt文件的printshell动词时,系统会拉起该文件类型默认关联的打印处理程序,txt文件默认绑定的处理程序是记事本(notepad.exe)。CreateNoWindow配置仅对控制台程序生效,ProcessWindowStyle.Hidden是传给目标进程的启动建议参数,记事本这类GUI程序会主动忽略该参数,启动时依然会短暂渲染主窗口,执行完打印逻辑后才退出,因此必然会出现弹窗闪现。
解决方案
按无弹窗效果从好到差排序:
- 最优方案:不依赖外部程序,直接使用.NET原生打印接口完成文本打印
引入System.Drawing.Printing命名空间,直接读取Temp.txt的文本内容,通过PrintDocument类配置打印机、绘制打印内容、提交打印任务,全程在当前应用进程内完成逻辑,不会唤起任何第三方程序,从根源上杜绝弹窗。 - 次优方案:直接调用记事本进程,传入打印命令参数
不通过shell动词唤起关联程序,直接指定启动notepad.exe,传入打印参数,最大程度压缩窗口闪现概率:
该方案在大部分Windows版本下可以消除明显弹窗,少数旧版本系统可能仍存在极短暂的窗口闪烁。var psi = new ProcessStartInfo(); psi.FileName = "notepad.exe"; // /p参数表示直接打印指定文件 psi.Arguments = "/p \"Temp.txt\""; psi.UseShellExecute = false; psi.CreateNoWindow = true; psi.WindowStyle = ProcessWindowStyle.Hidden; Process.Start(psi); - 备选方案:修改系统内txt文件的默认打印关联程序,替换为支持无窗口打印的文本处理工具,但该方案需要修改用户系统配置,不推荐在分发的应用中使用。
提示:不要尝试通过隐藏窗口、移动窗口到屏幕外等hack手段解决该问题,这类方案在不同系统版本、不同多显示器配置下兼容性极差,很容易出现失效情况。
内容的提问来源于stack exchange,提问作者Pacmandevil
相关产品推荐
相关产品推荐

