找回密码
 立即注册→加入我们

QQ登录

只需一步,快速开始

搜索
热搜: 下载 VB C 实现 编写
查看: 6456|回复: 3

简单介绍微软官方谷歌内核.NET浏览器控件WebView2

[复制链接]

12

主题

32

回帖

834

积分

用户组: 大·技术宅

UID
5148
精华
2
威望
7 点
宅币
736 个
贡献
30 次
宅之契约
0 份
在线时间
75 小时
注册时间
2019-7-17
发表于 2020-12-13 17:06:53 | 显示全部楼层 |阅读模式

欢迎访问技术宅的结界,请注册或者登录吧。

您需要 登录 才可以下载或查看,没有账号?立即注册→加入我们

×
来源
从不知道多老开始,VB6那时候就有一个浏览器控件,WebBrower,反正用的IE内核贼垃圾。  
Win10推出之后,微软的edge浏览器是用的edgeHTML这个内核,当时推出了一个浏览器控件叫 WebView 。   
这个控件体验也很差,早期还只支持 UWP 不支持 WIN32 。   
自从微软把edge浏览器变成了谷歌浏览器内核(Chromium),一切都开始明朗起来了。  
推出了新的浏览器控件 WebView2 ,接下来我们就讲一讲怎么玩耍这个东西。  

官方文档
如果你不想看我BB,直接去下面看官方文档。   
https://docs.microsoft.com/zh-cn/microsoft-edge/webview2/   

安装
首先,你必须在你的电脑上安装 WebView2 Runtime。可以说你不安装新版edge只要安装这个runtime就行了,这是为了防止做出的操作对系统环境使用的 edge 造成破坏或干扰。  
在软件的用户的电脑上也必须安装这个runtime才能正常工作。  
https://developer.microsoft.com/en-us/microsoft-edge/webview2/  
微软特地给你提供了离线安装版,在线安装版和固定不更新版本。  
在线安装版,就是 Evergreen Bootstrapper。   
离线安装版,就是 Evergreen Standalone Installer。   
Evergreen 指的是常青的,比如常青藤(意义不明)。  
这两个都只能安装到 C:\Program Files (x86)\Microsoft\EdgeWebView\Application 里面,而且好像会自动更新(具体不清楚,官方文档里写的很含糊)。  
还有一个解压即用版,就是 Fixed Version ,其实指的是固定版本,这个是不会自动更新的。  
如果你要使用这个 Fixed Version ,最好好好阅读一下这个 https://docs.microsoft.com/zh-cn/microsoft-edge/webview2/concepts/distribution   

安装好runtime之后,到你的 .NET 项目里面安装这个 NUGET 包。   

注意只能在以下平台运行:   


入门,链接跳转
下面我全部的内容使用的都是 .NET Framework 4.8 , Windows Forms, VB .NET 。  
不同的版本会有小的差异。   
你应该可以在这个控件工具箱列表里找到这个控件,放置出来就可以了。   

尽量不要操作右边的属性栏,把要初始化的代码都写在窗体的Load里面就好。  
下面我把这个控件实例命名为 edge 。  
在窗体的 Load 事件里面写上:   

  1. edge.Source = New Uri("https://www.baidu.com")
复制代码


Source 属性可以让控件跳到指定的链接。可以是 http://localhost,也可以是 file:///C:/xxx.html 格式的本地文件链接,还可以是 edge://version ,不过好像没有那个小恐龙游戏了。     
运行程序,看见窗口内的浏览器控件自动跳到了百度,说明咱们成功了。  

还有,别让用户手贱把这些进程给关了。  


设置运行环境,保存用户数据
在不设置运行环境的情况下,默认的用户数据是保存在webview2 runtime里面的,和用户平时的edge是隔离的,但是会在所有webview2程序里共享。   
如果你登陆了B站,并且选择了记住信息,那么下次打开程序还是会自动登陆B站。  
要避免共享,可以设置用户数据保存的文件夹,和其他人的独立开来。  
首先需要引用(如果是wpf的自己改):

  1. Imports Microsoft.Web.WebView2.Core
  2. Imports Microsoft.Web.WebView2.WinForms
复制代码

在窗体的 Load 事件里面写上:

  1. Dim ev = CoreWebView2Environment.CreateAsync(, AppContext.BaseDirectory)
  2. edge.EnsureCoreWebView2Async(ev.Result)
  3. edge.Source = New Uri("https://baidu.com")
复制代码

尽管这上面两个函数都是异步的,后面我会讲异步的关系。  
CoreWebView2Environment.CreateAsync这个函数有三个可选参数,留空都是默认,第一个是webview2 runtime的路径,就是有msedgewebview2.exe的那个文件夹。第二个是用户数据文件夹。第三个是一些可选设置,可以添加自定义进程启动设置。   
用户数据文件夹的那个路径下,webview2会创建一个文件夹叫做EBWebView,然后一切用户数据都是在里面的。  

正确设置 Core
CoreWebView2 是核心,用控件的只读属性 CoreWebView2 来获得,上面说到的 EnsureCoreWebView2Async 函数就是修改这个核心的设置。  
但是问题来了,这个异常奇葩,属性 CoreWebView2  获得的核心默认是 nothing (null) 的,你必须先使用 EnsureCoreWebView2Async 函数。  
但是这个函数居然是个异步函数,就很刺激了。  
经过我的测试,如果你直接 Task.Wait() 这个玩意会永远卡死下去。  
正确的办法是这样:  

  1. Private Async Sub Form1_Load(sender As Object, e As EventArgs) Handles Me.Load
  2.     Dim ev = CoreWebView2Environment.CreateAsync(, AppContext.BaseDirectory)
  3.     Await ev
  4.     Dim t As Task = edge.EnsureCoreWebView2Async(ev.Result)
  5.     Await t
  6.     Debug.WriteLine(edge.CoreWebView2.BrowserProcessId)
  7.     edge.Source = New Uri("https://baidu.com")
  8. End Sub
复制代码

能不能不设置核心就用这个控件呢?  
可以是可以,很多功能就少了,垃圾微软什么奇葩设计啊,core有的功能不继承到具体实现里面。  

阻止新窗口弹出
在实际使用中,这玩意会动不动打开新窗口,然后新窗口就完全不受程序控制了。所以我们可以给 core 新增一个事件,让新窗口的链接转移到本窗口里来。   
把下面的代码放在上面的 `Await t` 之后,就是要保证已经 `EnsureCoreWebView2Async` 完成了。  

  1. Dim core = edge.CoreWebView2
  2. AddHandler core.NewWindowRequested, Sub(ss As Object, ee As CoreWebView2NewWindowRequestedEventArgs)
  3.                                         ee.Handled = True
  4.                                         edge.Source = New Uri(ee.Uri)
  5.                                     End Sub
复制代码


这样就可以了。  

阻止用户使用浏览器自带功能
默认情况下,在网页右键是可以和普通浏览器一样打开菜单的,还居然可以打开一个F12窗口,真心NB。  
如果你不想让用户这么做的话,可以在 `core.Settings` 里面修改:  

  1. core.Settings.AreDefaultContextMenusEnabled = False
  2. core.Settings.AreDevToolsEnabled = False
  3. core.Settings.IsZoomControlEnabled = False
复制代码

第三个就是不允许用户通过 ctrl 加滚轮修改网页大小,还有一些设置自己探索一下,我就懒得说了。  

在网页上运行 javascript
在窗口上新增一个按钮,然后添加下列代码:   
必须使用 Async 和 Await 异步操作,Task.Wait() 或 Task.Result 都会一直卡死,无法继续!  

  1. Private Async Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
  2.     Dim t = edge.ExecuteScriptAsync("confirm('你是帅哥嘛?')")
  3.     Await t
  4.     Debug.WriteLine(t.Result)
  5. End Sub
复制代码


效果就是这样,然后debug那边应该会显示一个 true 或者 false ,返回的一定是字符串,如果啥都没有就是"null"了。  

网页传递信息到程序
这里说的是信息指的是 WebMessage ,使用方法如下:   
准备一个本地网页,随便写点什么,然后一定要在 <script> 里面写上下面这段javascript并引发与运行:

  1. var m = {}
  2. m.Age = 15
  3. m.Name = 'John'
  4. window.chrome.webview.postMessage(m)
复制代码

然后在程序代码里准备好 core,按下面这么操作,最好写在窗体Load里面。那个链接就写自己的本地html的文件链接就好。      

  1. Dim core = edge.CoreWebView2
  2. core.Settings.IsWebMessageEnabled = True
  3. edge.Source = New Uri("file:///D:/test.html")
复制代码

接下来给 webview2 控件新建一个事件:

  1. Private Sub edge_WebMessageReceived(sender As Object, e As CoreWebView2WebMessageReceivedEventArgs) Handles edge.WebMessageReceived
  2.     Debug.WriteLine(e.WebMessageAsJson)
  3. End Sub
复制代码

这样,在加载这个html,运行到那段js的时候,就会引发这个WebMessageReceived事件,传过来的是对象的json字符串。   

抓包
这个功能很有意思啊,可以拿来获取 httponly 的 cookie 和一些奇怪的 CSRF 之类的。   
首先要给core添加一条过滤规则,指定哪些链接和内容是我们要抓包的。  
如果想抓全部,就写这个:  

  1. core.AddWebResourceRequestedFilter("*", CoreWebView2WebResourceContext.All)
复制代码

接下来需要添加一个捕获事件,就像这样:  

  1. AddHandler core.WebResourceRequested, Sub(ss As Object, ee As CoreWebView2WebResourceRequestedEventArgs)
  2.                                             If ee.Request.Headers.Contains("Cookie") Then
  3.                                                 Debug.WriteLine(ee.Request.Headers.GetHeader("Cookie"))
  4.                                             End If
  5.                                             '最好先检测一下是不是Headers.Contains
  6.                                             '否则 GetHeader 遇到不存在的头会扔出一个错误。
  7.                                         End Sub
复制代码

在API里,CoreWebView2WebResourceRequestedEventArgs是有一个属性叫Response,不过没有合适的办法来获取它的值,访问就是nothing(null),如果在task里或者thread里去访问这个值,直接就throw了一个COM不支持的错误出来。  
github有神仙通过修改官方dll实现了获取这个`Response`,想看可以自己看看。  

回复

使用道具 举报

55

主题

271

回帖

9330

积分

用户组: 管理员

UID
77
精华
16
威望
237 点
宅币
8199 个
贡献
251 次
宅之契约
0 份
在线时间
253 小时
注册时间
2014-2-22
发表于 2021-1-20 04:29:54 | 显示全部楼层
记得以前有人发布过VB6可以用的CHROME.OCX,基于CHROME49,可以用于XP。
回复 赞! 靠!

使用道具 举报

1109

主题

1649

回帖

7万

积分

用户组: 管理员

一只技术宅

UID
1
精华
244
威望
743 点
宅币
24180 个
贡献
46222 次
宅之契约
0 份
在线时间
2294 小时
注册时间
2014-1-26
发表于 2021-1-27 00:26:54 | 显示全部楼层
美俪女神 发表于 2021-1-20 04:29
记得以前有人发布过VB6可以用的CHROME.OCX,基于CHROME49,可以用于XP。

这个牛,但是很可能在https问题上吃瘪
回复 赞! 靠!

使用道具 举报

55

主题

271

回帖

9330

积分

用户组: 管理员

UID
77
精华
16
威望
237 点
宅币
8199 个
贡献
251 次
宅之契约
0 份
在线时间
253 小时
注册时间
2014-2-22
发表于 2021-2-1 03:33:20 | 显示全部楼层
0xAA55 发表于 2021-1-27 00:26
这个牛,但是很可能在https问题上吃瘪

是的,我用CHROME49测试了一下,已经不能访问大多数HTTPS站点了。
回复 赞! 靠!

使用道具 举报

QQ|Archiver|小黑屋|技术宅的结界 ( 滇ICP备16008837号 )|网站地图

GMT+8, 2024-3-29 23:48 , Processed in 0.035941 second(s), 27 queries , Gzip On.

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表