一、c# WebView2简介   1.一开始使用WebBrowser,因为WebBrowser控件使用的是ie内核,经过修改注册表切换为Edge内核后, 发现Edge内核版本较低,加载一些视频网站提示“浏览器版本过低“,”视频无法加载“。

2.WebBrowser内核版本与WebView2比较

WebBrowser内核版本: 内核版本 (Version) Edge 18.9200 兼容 WebKit 537.36  Chrome 70  UserAgent: Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.9200

当前Edge内核版本: 内核版本 (Version)    WebKit 537.36  Chrome 111.0.0.0 UserAgent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.54

WebView2内核版本: 内核版本 (Version)    WebKit 537.36  Chrome 111.0.0.0 UserAgent:Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36 Edg/111.0.1661.51

可见,WebView2内核版本跟Edge一样,能顺利打开视频网站。WebBrowser内核版本过低。

WebView2加载视频网站

3.WebView2概述   Microsoft Edge WebView2 控件允许在本机应用中嵌入 web 技术(HTML、CSS 以及 JavaScript)。 WebView2 控件使用 Microsoft Edge 作为绘制引擎,以在本机应用中显示 web 内容。 虽说无法跨平台,但是在windows应用下做为原浏览器控件替代品还是不错的。

4.安装webview2    打开NuGet,搜索WebView2,安装之后,可以看到左侧就有了webview2控件,可以直接拖到窗体内。

二、问题分析1、关于登陆会话的问题 网页端必须打开小红书网站。小红书打开后,在浏览器Cookie里,有一个字段: web_session=040069b3b3f6625dade26f8d1d364b44f72186 这是记录登陆会话信息的。请求时headers中需要x-s、x-t,cookie中需要有web_session。 经测试,这个web_session会在浏览器保存一段时间,具体多久还有待验证(B站也有个类似的session,是一个月)。其它字段无关紧要。 不使用WebView2打开网站的话,需要到网站申请web_session,这里WebView2已经替我们弄好了。 通过c# WebView2获取cookie信息的方法:

private Dictionary mCookies = new Dictionary();//保存Cookie到字典中

///

/// WebView2异步获取cookie

///

/// 与cookie关联的域名

private async void getCookie(string url)

{

List cookieList = await webView.CoreWebView2.CookieManager.GetCookiesAsync(url);

mCookies.Clear();

for (int i = 0; i < cookieList.Count; ++i)

{

CoreWebView2Cookie cookie = webView.CoreWebView2.CookieManager.CreateCookieWithSystemNetCookie(cookieList[i].ToSystemNetCookie());

mCookies.Add(cookie.Name, cookie.Value);

}

}

///

/// 提取cookie中的一个字段;

///

/// 域名

/// 关键字,如:web_session

/// 延时(没用到)

///

public string getCookieEx(string url, string key, int t)

{

getCookie(url);

if (mCookies.ContainsKey(key))

{

string cookies = "";

foreach (var cookie in mCookies)

{

cookies += cookie.Key + "=" + cookie.Value + ";";

}

cookies = key + "=" + mCookies[key];

return cookies;

}

return null;

}

2.笔记信息接口

目前笔记信息接口: /api/sns/web/v1/feed 请求时headers中需要x-s、x-t,cookie中需要有web_session。

3.X-S 定位方法很多,可以全局搜 "X-s" 。往上找可以发现该段为 sign 方法,function sign(e, t) {}

全部复制到本地,然后根据报错把缺的方法和环境补一下,比如a0_0x4dee00、a0_0x5c27、a0_0x543e等方法,

然后把常用的navigator、location、document、window加上就好了。

该过程中根据具体错误再调试分析, 比如sign方法的 case "6",修改为var vr = window 、在case "7"中可以手动修改为 dr = ur['sNYMU'] 这里已经拿到了function sign(e, t) {}的JavaScript版,需要的+v:byc6352

三.解析原理及流程

  1、获取小红书笔记分享链接 Meta发布了一篇小红书笔记,快来看吧!  95mtho0hHhZLd1q  http://xhslink.com/AKXMyp,复制本条信息,打开【小红书】App查看精彩内容!  2、执行url重定向得到带来note_id的新链接 https://www.xiaohongshu.com/discovery/item/6430e99c00000000140259d3?app_platform=android&app_version=7.83.0&share_from_user_hidden=true&type=video&xhsshare=CopyLink&appuid=640d1628000000001400dc4d&apptime=1682740972  3、解析出note_id note_id=6430e99c00000000140259d3  4、调用JavaScript function sign(e, t) 签名得到X-s,X-t X-t: 1682742221056 X-s: Ogsb02Zv0gUJO2w6OB4UOjTl1g9CsBT+Oj9W0gsK1g13

  5、发送post请求:   (1)数据:

var args = '{\"source_note_id\":\"' + note_id + '\"}';

  (2)请求头(不会的+v:byc6352):

//JavaScript代码:

var headers = 'X-t: ' + o['X-t'] + '\r\nX-s: ' + o['X-s'] + '\r\nContent-Type: application/json;charset=UTF-8\r\nReferer: https://www.xiaohongshu.com/\r\nCookie: ' + cookie; 

  (3)服务器接口:

//JavaScript代码:

var api_url = 'https://edith.xiaohongshu.com/api/sns/web/v1/feed';

  (4)发送post:

//JavaScript代码:

var data = winning.getPostResult(api_url, args, headers);

  (5)得到笔记信息数据(json):

{"msg":"成功","data":{"cursor_score":"","items":[{"id":"6430e99c00000000140259d3","model_type":"note","note_card":{"at_user_list":[],"last_update_time":1680927132000,"title":"幻昼#治愈系风景","desc":"","user":{"user_id":"62c7b52a000000000303fdb4","nickname":"Meta","avatar":"https://sns-avatar-qc.xhscdn.com/avatar/62c7de8013ab526ecfbf1777.jpg"},"interact_info":{"share_count":"1","followed":false,"liked":false,"liked_count":"3","collected":false,"collected_count":"2","comment_count":"0"},"image_list":[{"file_id":"4e8ce0b1-ba6f-83bf-646b-bf8fea89341f","height":1280,"width":720,"url":"https://sns-img-hw.xhscdn.com/4e8ce0b1-ba6f-83bf-646b-bf8fea89341f","trace_id":"217/0/01e430e94079052e00100001875f0f3462_0.jpg"}],"tag_list":[],"time":1680927132000,"ip_location":"云南","note_id":"6430e99c00000000140259d3","share_info":{"un_share":false},"type":"video","video":{"media":{"video_id":136287668638655138,"video":{"drm_type":0,"stream_types":[259],"biz_name":110,"biz_id":"280402856711969235","duration":257,"md5":"5bb4036b378ab014d2114784bc147f10","hdr_type":0},"stream":{"h265":[],"av1":[],"h264":[{"audio_duration":250729,"master_url":"http://sns-video-hw.xhscdn.com/stream/110/259/01e430e99c7922a201037003875f169774_259.mp4","vmaf":-1,"stream_desc":"WM_X264_MP4","duration":256800,"size":68608344,"fps":30,"psnr":0,"ssim":0,"quality_type":"HD","height":1280,"avg_bitrate":2137331,"default_stream":0,"width":720,"video_duration":256800,"audio_bitrate":64035,"audio_channels":2,"backup_urls":["http://sns-video-bd.xhscdn.com/stream/110/259/01e430e99c7922a201037003875f169774_259.mp4","http://sns-video-qc.xhscdn.com/stream/110/259/01e430e99c7922a201037003875f169774_259.mp4?sign=6c5ffdf48d9c842405bb3e3a5fa361e7&t=644e8f54","http://sns-video-al.xhscdn.com/stream/110/259/01e430e99c7922a201037003875f169774_259.mp4"],"stream_type":259,"format":"mp4","volume":0,"video_codec":"h264","hdr_type":0,"rotate":0,"video_bitrate":2068304,"audio_codec":"aac","weight":62}]}},"image":{"thumbnail_fileid":"110/0/01e430e99c7922a200100001875f111ff3_0.webp"},"capa":{"duration":256},"consumer":{"origin_video_key":"spectrum/1000g2f02adqphsqh20005om7mkl0vvdklvh95l8"}}}}],"current_time":1682743347282},"code":0,"success":true}

  6、解析笔记信息数据(json):   如果data.items[i].note_card.type='video' 说明该笔记为视频内容;   如果data.items[i].note_card.type='normal' 说明该笔记为图文内容;   7、一张图看懂无水印视频、无水印封面所在位置:   PHOTO_HOST='https://sns-img-hw.xhscdn.com/';  //无水印封面服务器   VIDEO_HOST='http://sns-video-bd.xhscdn.com/';  //无水印视频服务器

 

四、WebView2中C#和JavaScript代码互操作 1.需要创建一个ScriptHost对象,并注册到WebView2中:

///

/// 网页调用C#方法

///

[ClassInterface(ClassInterfaceType.AutoDual)]

[ComVisible(true)]

public class ScriptHost

2.在WebView2初始化完成事件中注册ScriptHost对象

///

/// CoreWebView2初始化完成

///

///

///

private void webView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)

{

//注册winning,winasync脚本c#互操作

webView.CoreWebView2.AddHostObjectToScript("scriptHost", scriptHost);

//注册全局变量winning 同步操作;winasync:异步操作;

webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var winasync= window.chrome.webview.hostObjects.scriptHost;");

webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var winning= window.chrome.webview.hostObjects.sync.scriptHost;");

}

3.ScriptHost中暴露的公共方法,都可以在前端JavaScript中调用。

///

/// 日志记录(JavaScript前端调用

///

/// JavaScript前端信息

public void log(string message)

{

Log.i(message);//记录到文本文件中

//MessageBox.Show(message);

}

..............................................

winning.log(data);//JavaScript端调用(同步调用);

五、下载封面及视频

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net.Configuration;

using System.Text;

using System.Threading.Tasks;

namespace XhsVideo

{

///

/// 下载视频

///

internal class VideoDown

{

public int id { get; set; }

public VideoInfo video { get; set; }

public string savedir { get; set; }

public string msg { get; set; }

public bool success { get; set; }

public string headers { get; set; }

public VideoDown(int id,VideoInfo video,string savdir,string headers=null) {

this.id = id;

this.video = video;

this.savedir = savdir;

if (System.IO.Directory.Exists(savdir)) System.IO.Directory.CreateDirectory(savdir);

this.headers = headers;

}

public void process()

{

string filename = MakeValidFileName( video.title,""); //去除文件名中的非法字符

string videoname = savedir + "\\" + filename + ".mp4";

string covername = savedir + "\\" + filename + ".webp";

if (System.IO.File.Exists(covername)) System.IO.File.Delete(covername);

if (System.IO.File.Exists(videoname)) System.IO.File.Delete(videoname);

Log.i(videoname);

Log.i(covername);

//NetHelper.downloadfileAsync(video.videoUrl, videoname);

NetHelper.downloadfileAsync(video.coverUrl, covername);

NetHelper.DownloadFileAsync(video.videoUrl, videoname, showProgress);//显示下载视频的进度

}

/**

* @param text: 原始串

* @param replacement: 要替换的字符串

*/

public static string MakeValidFileName(string text, string replacement = "_")

{

StringBuilder str = new StringBuilder();

var invalidFileNameChars = System.IO.Path.GetInvalidFileNameChars();

foreach (var c in text)

{

if (invalidFileNameChars.Contains(c))

{

str.Append(replacement ?? "");

}

else

{

str.Append(c);

}

}

return str.ToString();

}

///

/// 下载视频的进度回调函数

///

/// 下载进度信息

public void showProgress(string msg)

{

this.msg = msg;

Log.i(msg);

fMainForm.GetFMainForm().syncContext.Send(fMainForm.GetFMainForm().SetTextSafePost, this);//Post 将信息发送到窗体显示

}

}

///

/// 视频信息类,由:标题,封面地址,视频地址组成。

///

public class VideoInfo

{

public string title { get; set; }

public string coverUrl { get; set; }

public string videoUrl { get; set; }

public VideoInfo(string title,string coverUrl,string videoUrl)

{

this.title = title;

this.coverUrl = coverUrl;

this.videoUrl = videoUrl;

}

}

}

六、日志记录

using System;

using System.Collections.Generic;

using System.IO;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

namespace XhsVideo

{

///

/// 日志记录 到文本文件

///

internal class Log

{

private static Log log;

private static string logName;

private Log(string filename) {

logName = filename;

}

public static Log GetLog(string filename)

{

if (log == null) { log = new Log(filename); }

return log;

}

public static Log GetLog()

{

return log;

}

public static void i(string msg)

{

string now = DateTime.Now.ToString();

string[] text = new string[2];

text[0] = now;

text[1] = msg;

try

{

using (StreamWriter sw = new StreamWriter(logName,true,Encoding.UTF8))

{

foreach (string s in text)

{

sw.WriteLine(s);

}

sw.Close();

}

}

catch (Exception e)

{

//Console.WriteLine("Exception: " + e.Message);

}

finally

{

//Console.WriteLine("Executing finally block.");

}

}

}

}

七、网络访问组件

using System;

using System.Collections.Generic;

using System.Linq;

using System.Net.Http.Headers;

using System.Net.Http;

using System.Text;

using System.Threading.Tasks;

using System.Net;

using System.IO;

using System.Windows.Forms;

namespace XhsVideo

{

///

/// 网络访问组件

///

internal class NetHelper

{

#region 文件下载

///

/// 下载文件

///

/// 文件下载地址

/// 本地保存路径+名称

/// 下载回调(总长度,已下载,进度)

///

///

public static async Task DownloadFileAsync(string url, string savePath, Action downloadCallBack = null)

{

try

{

downloadCallBack?.Invoke($"文件【{url}】开始下载!");

HttpResponseMessage response = null;

using (HttpClient client = new HttpClient())

response = await client.GetAsync(url);

if (response == null)

{

downloadCallBack?.Invoke("文件获取失败");

return;

}

var total = response.Content.Headers.ContentLength ?? 0;

var stream = await response.Content.ReadAsStreamAsync();

var file = new FileInfo(savePath);

using (var fileStream = file.Create())

using (stream)

{

if (downloadCallBack == null)

{

await stream.CopyToAsync(fileStream);

downloadCallBack?.Invoke($"文件【{url}】下载完成!");

}

else

{

byte[] buffer = new byte[1024];

long readLength = 0;

int length;

double temp = 0;

string msg = "";

while ((length = await stream.ReadAsync(buffer, 0, buffer.Length)) != 0)

{

// 写入到文件

fileStream.Write(buffer, 0, length);

//更新进度

readLength += length;

double progress = Math.Round((double)readLength / total * 100, 2, MidpointRounding.AwayFromZero);//.ToZero

if ((progress % 1) == 0 && (progress % 1) != temp)

{

msg = $"总大小:【{total}】,已下载:【{readLength}】,进度:【{progress}】";

downloadCallBack?.Invoke(msg);

}

temp = progress % 1;

//下载完毕立刻关闭释放文件流

if (total == readLength && progress == 100)

{

fileStream.Close();

fileStream.Dispose();

msg = $"总大小:【{total}】,已下载:【{readLength}】,进度:【{progress}】下载完成。";

downloadCallBack?.Invoke(msg);

}

}

}

}

}

catch (Exception ex)

{

downloadCallBack?.Invoke($"下载文件失败:{ex.Message}!");

}

}

#endregion

///

/// 异步下载文件

///

///

///

public static async void downloadfileAsync(string url,string filename)

{

using (var web = new WebClient())

{

await web.DownloadFileTaskAsync(url, filename);

}

}

///

/// 地址重定向

///

/// 原地址

/// 域名

/// userAgent

/// 重定向后的地址

public static string getRedirectedUrl(string url, string domain, string ua)

{

var str = getRedirectedUrl_T(url);

return str.Result;

}

///

/// 异步地址重定向

///

///

///

private static async Task getRedirectedUrl_T(string url)

{

try

{

var handler = new HttpClientHandler()

{

AllowAutoRedirect = false

};

var client = new HttpClient(handler);

var response = await client.GetAsync(url).ConfigureAwait(continueOnCapturedContext: false);

int statuscode = (int)response.StatusCode;

if (statuscode == 307)

{

string location = response.Headers.Location.ToString();

return location;

}

if (statuscode == 302)

{

string location = response.Headers.Location.ToString();

return location;

}

else

{

return "";

}

}

catch (Exception e)

{

System.Diagnostics.Debug.WriteLine("getRedirectedUrl_T:" + e.ToString());

return "";

}

}

//---------------------------------------------------------------post---------------------------------------------------------------------

///

/// Post访问

///

/// 访问地址

/// 数据

/// HTTP头

/// 返回服务器JSON数据

public static string getPostResult(string url, string args, string headers)

{

var str = getPostResult_T(url, args, headers);

return str.Result;

}

///

/// 异步post调用

///

///

///

///

///

private static async Task getPostResult_T(string url, string args, string headers)

{

try

{

var handler = new HttpClientHandler() { UseCookies = false };

var client = new HttpClient(handler);// { BaseAddress = baseAddress };

client.Timeout = TimeSpan.FromSeconds(20);

var message = new HttpRequestMessage(HttpMethod.Post, url);

message.Content = new StringContent(args);

message.Content.Headers.ContentType = new MediaTypeHeaderValue("application/json");

//message.Headers;

Dictionary dictionary = ParseToDictionary(headers);

foreach (var pair in dictionary)

{

if (pair.Key.Equals("content-type")) continue;

if (pair.Key.Equals("Content-Type")) continue;

message.Headers.Add(pair.Key, pair.Value);

}

var result = await client.SendAsync(message).ConfigureAwait(continueOnCapturedContext: false);

result.EnsureSuccessStatusCode();

return await result.Content.ReadAsStringAsync();

}

catch (Exception e)

{

//EventLog.GetEventLogs(e.ToString);

System.Diagnostics.Debug.WriteLine("getPostResultEx_T:" + e.ToString());

///console.write(e.ToString());

return "";

}

}

///

/// 字符串解析为字典数据

///

/// 以回车换行符分割的字符串

/// 字典数据

private static Dictionary ParseToDictionary(string str)

{

Dictionary result = new Dictionary();

string str1 = str;

int i = str1.IndexOf("\r\n");

int j = 0;

while (i > 0)

{

string str2 = str1.Substring(0, i);

j = str2.IndexOf(":");

if (j > 0)

{

string str21 = str2.Substring(0, j);

string str22 = str2.Substring(j + 1);

result.Add(str21, str22);

}

str1 = str1.Substring(i + 2);

i = str1.IndexOf("\r\n");

}

j = str1.IndexOf(":");

if (j > 0)

{

string str21 = str1.Substring(0, j);

string str22 = str1.Substring(j + 1);

result.Add(str21, str22);

}

return result;

}

//-------------------------------------------------------------------GET -------------------------------------------------------------------

///

/// 获取服务器端的HTML代码

///

///

///

public static string getHtmlCode(string url)

{

var str = getHtmlCode_T(url);

return str.Result;

}

///

/// 异步获取服务器端的HTML代码

///

///

///

public static async Task getHtmlCode_T(string url)

{

try

{

var http = new HttpClient();

http.Timeout = TimeSpan.FromSeconds(10);

var result = await http.GetStringAsync(url).ConfigureAwait(continueOnCapturedContext: false);

return result;

}

catch (Exception e)

{

//EventLog.GetEventLogs(e.ToString);

System.Diagnostics.Debug.WriteLine("错误信息在这儿:" + e.ToString());

///console.write(e.ToString());

Log.i(e.ToString());

return "";

}

}

}

}

八、ScriptHost与JavaScript交互(主要流程):

using Microsoft.Web.WebView2.Core;

using Microsoft.Web.WebView2.WinForms;

using System;

using System.Collections.Generic;

using System.Linq;

using System.Runtime.InteropServices;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;

using static System.Windows.Forms.VisualStyles.VisualStyleElement;

using System.Threading;

using System.Security.Policy;

using System.Net.Http;

using System.Net.Http.Headers;

namespace XhsVideo

{

///

/// 网页调用C#方法

///

[ClassInterface(ClassInterfaceType.AutoDual)]

[ComVisible(true)]

public class ScriptHost

{

private WebView2 webView;

private Dictionary mCookies = new Dictionary();//保存Cookie到字典中

private string mUrl;

public static ScriptHost scriptHost = null;

private ScriptHost(WebView2 webView)

{

scriptHost = this;

this.webView = webView;

//注册事件侦听,加载页面完成时,获取cookie;

this.webView.NavigationCompleted += new System.EventHandler(this.webView_NavigationCompleted);

//webView初始化完成后注册与JavaScript交互

this.webView.CoreWebView2InitializationCompleted += new System.EventHandler(this.webView_CoreWebView2InitializationCompleted);

}

public static ScriptHost GetScriptHost(WebView2 webView)

{

if (scriptHost == null) scriptHost = new ScriptHost(webView);

return scriptHost;

}

///

/// 日志记录(JavaScript前端调用

///

/// JavaScript前端信息

public void log(string message)

{

Log.i(message);//记录到文本文件中

//MessageBox.Show(message);

}

///

/// 提取cookie中的一个字段;

///

/// 域名

/// 关键字,如:web_session

/// 延时(没用到)

///

public string getCookieEx(string url, string key, int t)

{

getCookie(url);

if (mCookies.ContainsKey(key))

{

string cookies = "";

foreach (var cookie in mCookies)

{

cookies += cookie.Key + "=" + cookie.Value + ";";

}

cookies = key + "=" + mCookies[key];

//cookies = "web_session=040069b3b3f6625dade26f8d1d364b44f72186";

return cookies;

}

return null;

}

///

/// WebView2异步获取cookie

///

/// 与cookie关联的域名

private async void getCookie(string url)

{

List cookieList = await webView.CoreWebView2.CookieManager.GetCookiesAsync(url);

mCookies.Clear();

for (int i = 0; i < cookieList.Count; ++i)

{

CoreWebView2Cookie cookie = webView.CoreWebView2.CookieManager.CreateCookieWithSystemNetCookie(cookieList[i].ToSystemNetCookie());

mCookies.Add(cookie.Name, cookie.Value);

}

}

///

/// 解析并下载由JavaScript返回的信息

///

///

public void getJsResult(string text)

{

Log.i(text);

string temp = text;

string[] ss = text.Split(',');

string title = "";

string coverUrl = "";

string videoUrl = "";

string origin_video_key = "";

string trace_id = "";

int id = 0;

foreach (string s in ss)

{

string[] dd = s.Split('=');

if (dd.Length == 2)

{

if (dd[0].Equals("title")) title = dd[1];

if (dd[0].Equals("cover_url")) coverUrl = dd[1];

if (dd[0].Equals("video_url")) videoUrl = dd[1];

if (dd[0].Equals("origin_video_key")) origin_video_key = dd[1];

if (dd[0].Equals("trace_id")) trace_id = dd[1];

if (dd[0].Equals("id")) id = int.Parse(dd[1]);

}

}

videoUrl = "http://sns-video-hw.xhscdn.com/" + origin_video_key;//无水印视频

coverUrl = "https://sns-img-qc.xhscdn.com/" + trace_id;//无水印封面

VideoInfo video = new VideoInfo(title, coverUrl, videoUrl);//创建视频信息对象

VideoDown videodown=new VideoDown(id, video, Config.savedir);//创建视频下载对象

videodown.process();//执行下载

}

//---------------------------------------------------------socket--------------------------------------------------------------------------------

///

/// 重定向链接,该方法由JavaScript调用;

///

///

///

///

///

public string getRedirectedUrl(string url, string domain, string ua)

{

return NetHelper.getRedirectedUrl(url, domain, ua);

}

///

/// 提交post请求,该方法由JavaScript调用;

///

///

///

///

///

public string getPostResultEx(string url, string args, string headers)

{

return NetHelper.getPostResult(url, args, headers);

}

//-----------------------------------------------------------事件---------------------------------------------------------------------------

///

/// 加载完页面时,获取cookie

///

///

///

private void webView_NavigationCompleted(object sender, CoreWebView2NavigationCompletedEventArgs e)

{

string url = webView.Source.Host.ToString();

url = "https://" + url;

getCookie(url);

}

///

/// CoreWebView2初始化完成

///

///

///

private void webView_CoreWebView2InitializationCompleted(object sender, CoreWebView2InitializationCompletedEventArgs e)

{

//注册winning,winasync脚本c#互操作

webView.CoreWebView2.AddHostObjectToScript("scriptHost", scriptHost);

//注册全局变量winning 同步操作;winasync:异步操作;

webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var winasync= window.chrome.webview.hostObjects.scriptHost;");

webView.CoreWebView2.AddScriptToExecuteOnDocumentCreatedAsync("var winning= window.chrome.webview.hostObjects.sync.scriptHost;");

}

}

}

因为涉及的技术知识点太多了,后续继续完善下载无水印图文。

                                         (未完待续)

查看原文