使用Selenium C#时Ctrl+P无法触发打印保存PDF该如何解决
之前方案失效原因
SendKeys.SendWait是系统级按键接口,发送前未保证浏览器/打印弹窗为当前激活窗口,按键会发送到其他聚焦的程序中Actions类的按键操作是发送给浏览器渲染的网页DOM的,无法触发系统级的打印快捷键,也无法操作系统原生打印弹窗- 打印弹窗属于系统原生窗口,不属于浏览器的标签页窗口,
driver.SwitchTo().Window对其无效,且未给弹窗预留足够的加载时间直接发送回车也会失效
推荐解决方案:使用Chrome DevTools Protocol(CDP)直接生成PDF(无弹窗,生产环境可用)
该方案无需操作任何系统弹窗,直接调用浏览器内核接口渲染生成PDF,不受窗口聚焦、弹窗拦截等因素影响,仅支持Chromium内核浏览器(Chrome、Edge等),要求Selenium版本≥4.0。
示例代码:
using OpenQA.Selenium; using OpenQA.Selenium.Chrome; using OpenQA.Selenium.DevTools; // 注意:命名空间的版本号要和本地安装的Chrome浏览器大版本一致,例如Chrome 120就用V120 using OpenQA.Selenium.DevTools.V120.Page; // 初始化浏览器 var chromeOptions = new ChromeOptions(); // 可选:开启无头模式,后台运行不弹出浏览器界面 chromeOptions.AddArgument("--headless=new"); var driver = new ChromeDriver(chromeOptions); // 打开目标页面,等待页面完全加载 driver.Url = "你需要打印的网页地址"; // 可替换为你自己的页面加载等待逻辑 Thread.Sleep(3000); // 初始化CDP会话 var devToolsSession = (driver as IDevTools).GetDevToolsSession(); var pageDomain = devToolsSession.GetVersionSpecificDomains<DevTools.V120.DevToolsSessionDomains>().Page; // 配置PDF导出参数 var pdfSettings = new PrintToPDFCommandSettings { Landscape = false, // 是否横向打印 PrintBackground = true, // 是否打印页面背景色、背景图 PaperWidth = 8.27, // A4纸宽度,单位英寸 PaperHeight = 11.69, // A4纸高度 MarginTop = 0.4, MarginBottom = 0.4, MarginLeft = 0.4, MarginRight = 0.4 }; // 执行打印,返回base64格式的PDF内容 var printResult = pageDomain.PrintToPDF(pdfSettings).GetAwaiter().GetResult(); byte[] pdfData = Convert.FromBase64String(printResult.Data); // 保存到本地路径 File.WriteAllBytes(@"C:\你的保存路径\输出文件.pdf", pdfData); // 释放资源 driver.Quit();
备选方案:修复原生弹窗操作逻辑(仅适合本地调试用,不稳定)
如果必须操作系统打印弹窗,可通过Win32 API强制激活窗口+增加等待时间实现,代码如下:
// 首先引入Win32 API,用于激活窗口 [System.Runtime.InteropServices.DllImport("user32.dll")] private static extern bool SetForegroundWindow(IntPtr hWnd); // 触发打印弹窗 ((IJavaScriptExecutor)driver).ExecuteScript("window.print()"); // 等待弹窗完全加载,可根据你的系统响应速度调整时长 Thread.Sleep(2000); // 激活浏览器窗口,保证按键发送到打印弹窗 SetForegroundWindow((IntPtr)driver.CurrentWindowHandle); // 发送Alt+P快捷键触发打印(Windows系统打印弹窗默认快捷键,比回车更可靠) SendKeys.SendWait("%p"); // 等待保存文件弹窗弹出 Thread.Sleep(1000); // 输入保存路径后回车确认 SendKeys.SendWait(@"C:\你的保存路径\输出文件.pdf{ENTER}");
内容的提问来源于stack exchange,提问作者lightcoder
相关产品推荐
相关产品推荐

