惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

W
WeLiveSecurity
The Last Watchdog
The Last Watchdog
Application and Cybersecurity Blog
Application and Cybersecurity Blog
G
Google Developers Blog
博客园 - 叶小钗
雷峰网
雷峰网
人人都是产品经理
人人都是产品经理
博客园_首页
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
博客园 - 三生石上(FineUI控件)
Help Net Security
Help Net Security
Cloudbric
Cloudbric
AI
AI
N
News | PayPal Newsroom
博客园 - 聂微东
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
美团技术团队
Stack Overflow Blog
Stack Overflow Blog
SecWiki News
SecWiki News
H
Heimdal Security Blog
H
Hackread – Cybersecurity News, Data Breaches, AI and More
MyScale Blog
MyScale Blog
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
S
Security @ Cisco Blogs
Google DeepMind News
Google DeepMind News
V
V2EX
大猫的无限游戏
大猫的无限游戏
阮一峰的网络日志
阮一峰的网络日志
S
Security Affairs
L
LangChain Blog
The Hacker News
The Hacker News
F
Full Disclosure
aimingoo的专栏
aimingoo的专栏
Hacker News - Newest:
Hacker News - Newest: "LLM"
腾讯CDC
Webroot Blog
Webroot Blog
A
About on SuperTechFans
H
Hacker News: Front Page
Cyberwarzone
Cyberwarzone
WordPress大学
WordPress大学
L
LINUX DO - 热门话题
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
Attack and Defense Labs
Attack and Defense Labs
M
MIT News - Artificial intelligence

博客园 - zhaotianff

解决IIS服务器typecho上传附件后无法访问的问题 Visual Studio编译过程中拷贝文件的一些实用小技巧 Jenkins快速入门教程 .NET是什么?为什么要选择.NET? 如何在WPF中实现类似DevOps的自动化流程 一文带你搞懂医疗器械设计开发全生命周期 Windows如何清除本机记录的git用户名和密码 HL7协议详解 医疗行业 GDT 数据格式详解 一文带你搞懂C# 异步编程(async/await)底层原理 不同.NET版本中的WPF新增功能 如何在WPF中使用 Fluent 主题 Windows平台下的各种原生UI框架介绍 C#如何Hook托管函数 WinDbg 用户层调试进阶教程 Windows编程的一些基础理论 推荐一款优秀的Windows经典文件管理器项目-WinFile Windows如何阻止应用程序联网 如何在WPF中捕获窗口外的事件 如何查看Windows进程的启动来源 Visual Studio 2026新解决方案格式slnx详解 我的微软MVP申请通过了 WPF MVVM实战系列教程(八、Prism DialogService, 对话框服务) WPF MVVM实战系列教程(七、Prism模块化) WPF 性能优化实战指南 WPF MVVM实战系列教程(六、Prism区域导航) WPF MVVM实战系列教程(五、Prism中的MVVM) WPF MVVM实战系列教程(四、Prism中的依赖注入) 微软 IDE 新纪元:Visual Studio 2026 初体验 Windows 7无法安装VMWare Tools的解决办法 WPF MVVM实战系列教程(三、创建Bootstrapper/启动器) WPF MVVM实战系列教程(二、使用Visual Studio 创建Prism项目) WPF MVVM实战系列教程(一、Prism框架介绍)
如何在C#中使用Chromium headless(无头模式)浏览器
zhaotianff · 2026-05-20 · via 博客园 - zhaotianff

CEFSharp

在前面的文章中,我介绍过CEFSharp

CEF 全称是Chromium Embedded Framework(Chromium嵌入式框架),是个基于Google Chromium项目的开源Web browser控件,支持Windows, Linux, Mac平台。

CEFSharp就是CEF的C#移植版本。

CEFSharp提供了一个headless(无头模式)版本。

所谓无头模式(Headless Mode),就是浏览器不显示 GUI 界面,后台完整运行渲染引擎与 JS 引擎,适合服务器 / 自动化场景。

如何使用CEFSharp的无头模式

这里提供了一个CefSharp.OffScreen包,基础使用步骤如下:

1、创建一个控制台项目,nuget安装CefSharp.OffScreen包

image

注意:截止最新稳定版 147.0.100,CEFSharp.OffScreen.NETCore包仅支持.NET 6.0-windows版本,后续 不知道会不会支持.NET 6.0以上版本

2、项目属性 → 首选 32 位 / 64 位一致

 

image

3、 设置为 STA 线程

1  class Program
2  {
3      [STAThread]
4      static async Task Main(string[] args)
5      {
6 
7      }
8 }

4、基础使用代码如下

三、绑定核心事件

private static void BindBrowserEvent()
{
    // 页面加载完成
    _browser.LoadCompleted += (s, e) =>
    {
        Console.WriteLine($"页面加载完成:{e.Url} 状态:{e.HttpStatusCode}");
    };

    // 渲染画面回调(每一帧都会触发)
    _browser.Paint += (s, e) =>
    {
        // e.Bitmap 就是当前网页截图
        if (e.Bitmap != null)
        {
            // 只保存一次,避免频繁保存
            static bool saved = false;
            if (!saved)
            {
                e.Bitmap.Save("网页截图.png");
                saved = true;
                Console.WriteLine("截图已保存");
            }
        }
    };

    // JS控制台日志捕获
    _browser.ConsoleMessage += (s, e) =>
    {
        Console.WriteLine($"JS日志:{e.Message}");
    };
}

四、封装加载网页方法

/// <summary>
/// 等待页面加载完成
/// </summary>
private static Task LoadUrlAsync(string url)
{
    var tcs = new TaskCompletionSource<bool>();
    void LoadComplete(object sender, LoadCompletedEventArgs e)
    {
        _browser.LoadCompleted -= LoadComplete;
        tcs.SetResult(true);
    }
    _browser.LoadCompleted += LoadComplete;
    _browser.Load(url);
    return tcs.Task;
}

五、所有常用功能合集

private static async Task RunAllDemoFunc()
{
    // 1. 执行JS获取返回值
    var jsResult = await _browser.EvaluateScriptAsync("document.title");
    if (jsResult.Success)
    {
        Console.WriteLine("网页标题:" + jsResult.Result);
    }

    // 2. 点击页面元素(坐标点击)
    // x,y 网页相对坐标
    _browser.BrowserHost.SendMouseClickEvent(
        x: 120, y: 120, 
        mouseButtonType: MouseButtonType.Left, 
        mouseUp: false, clickCount: 1);

    await Task.Delay(200);
    _browser.BrowserHost.SendMouseClickEvent(
        120, 120, MouseButtonType.Left, true, 1);

    // 3. 输入键盘内容
    _browser.BrowserHost.SendKeyEvent(KeyEventType.KeyDown, (int)Keys.H);
    _browser.BrowserHost.SendKeyEvent(KeyEventType.Char, 'H');
    _browser.BrowserHost.SendKeyEvent(KeyEventType.KeyUp, (int)Keys.H);

    // 4. 网页后退/前进/刷新
    _browser.Back();
    _browser.Forward();
    _browser.Reload();

    // 5. 导出网页为PDF
    var pdfSettings = new PdfPrintSettings
    {
        Landscape = false,
        PrintBackground = true
    };
    await _browser.PrintToPdfAsync("网页导出.pdf", pdfSettings);
    Console.WriteLine("PDF导出完成");

    // 6. 设置Cookie
    var cookieManager = Cef.GetGlobalCookieManager();
    cookieManager.SetCookie("https://baidu.com", new Cookie
    {
        Name = "testCookie",
        Value = "123456",
        Domain = ".baidu.com"
    });

    // 7. 获取当前URL
    Console.WriteLine("当前地址:" + _browser.Address);
}

六、关键注意事项

  1. 必须 STA 线程 控制台 Main 加 [STAThread],否则渲染卡死、无画面
  2. 资源释放 ChromiumWebBrowser 一定要Dispose(),最后Cef.Shutdown()
  3. 无头无窗口 看不到界面,所有交互只能代码模拟
  4. 多线程禁止直接操作 Browser 只能在 CEF 事件线程 / 主线程调用
  5. 截图卡顿 Paint 事件每一帧触发,加标记只保存一次即可
  6. .NET 6/7/8 兼容 优先用 CefSharp.OffScreen 112+ 版本

七、截图示例

[STAThread]
static void ScreenshotDemo()
{
    var settings = new CefSettings { DisableGpu = true };
    Cef.Initialize(settings);

    using var browser = new ChromiumWebBrowser("https://www.qq.com", 1024, 768);
    browser.LoadCompleted += (s, e) =>
    {
        Task.Delay(1000).Wait();
    };

    browser.Paint += (s, e) =>
    {
        e.Bitmap?.Save("QQ截图.jpg");
        Console.WriteLine("截图完成");
    };

    System.Threading.Thread.Sleep(3000);
    browser.Dispose();
    Cef.Shutdown();
}

八、常用 API 速查

  • EvaluateScriptAsync 执行 JS
  • SendMouseClickEvent 模拟点击
  • SendKeyEvent 模拟键盘
  • PrintToPdfAsync 导出 PDF
  • LoadHtml 直接加载本地 HTML
  • ZoomLevel 网页缩放

https://www.cnblogs.com/zhaotianff/p/13528507.html