WPF 使用 WebView2

Fork Me On Github
zodream 编程技术 C# 2020年07月

安装SDK

必须安装 Microsoft Edge (Chromium) Canary channel 浏览器

NuGet 安装 Microsoft.Web.WebView2 预发行版 0.9.538-prerelease,正式版0.9.538安装是没用的

使用

xml
   
xmlns:wv2="clr-namespace:Microsoft.Web.WebView2.Wpf;assembly=Microsoft.Web.WebView2.Wpf"

<wv2:WebView2 x:Name="Browser" Source="https://www.baidu.com"/>
123

相关事件

SourceChanged 可以获取当前的网址,可以更新网页通过 js 修改的网址

NavigationStarting 网页加载开始

NavigationCompleted 网页加载完成

CoreWebView2Ready CoreWebView2 初始化完成,可以进行 CoreWebView2 上的事件绑定

CoreWebView2.NewWindowRequested 加载新标签之前触发,可以通过 e.Handled = true; 阻止触发,e.Uri 为要跳转的网址

代码跳转

c#
 
Browser.Source = new Uri(url);
1

获取源代码

主要通过 ExecuteScriptAsync 方法执行 js 代码,返回的值都是 JSON 过的。如果 JSON 编码失败则返回 null

c#
        
using Newtonsoft.Json;

var html = await Browser.ExecuteScriptAsync("document.getElementsByTagName('html')[0].innerHTML");
if (string.IsNullOrWhiteSpace(html))
{
    return html;
}
return "<!DOCTYPE html><html>" + JsonConvert.DeserializeObject(html) + "</html>";
12345678

获取 cookie

c#
                                                                        
using System;
using System.ComponentModel;
using System.Net;
using System.Security;
using System.Security.Permissions;
using System.Text;

/// <summary></summary>  
/// 取得WebBrowser的完整Cookie。  
/// 因为默认的webBrowser1.Document.Cookie取不到HttpOnly的Cookie  
///   
public class FullWebBrowserCookie
{

    [SecurityCritical]
    public static string GetCookieInternal(Uri uri, bool throwIfNoCookie)
    {
        uint pchCookieData = 0;
        var url = UriToString(uri);
        const uint flag = (uint)NativeMethods.InternetFlags.INTERNET_COOKIE_HTTPONLY;

        //Gets the size of the string builder  
        if (NativeMethods.InternetGetCookieEx(url, null, null, ref pchCookieData, flag, IntPtr.Zero))
        {
            pchCookieData++;
            var cookieData = new StringBuilder((int)pchCookieData);

            //Read the cookie  
            if (NativeMethods.InternetGetCookieEx(url, null, cookieData, ref pchCookieData, flag, IntPtr.Zero))
            {
                DemandWebPermission(uri);
                return cookieData.ToString();
            }
        }

        var lastErrorCode = 0;

        if (throwIfNoCookie || (lastErrorCode != (int)NativeMethods.ErrorFlags.ERROR_NO_MORE_ITEMS))
        {
            throw new Win32Exception(lastErrorCode);
        }

        return null;
    }

    private static void DemandWebPermission(Uri uri)
    {
        var uriString = UriToString(uri);

        if (uri.IsFile)
        {
            var localPath = uri.LocalPath;
            new FileIOPermission(FileIOPermissionAccess.Read, localPath).Demand();
        }
        else
        {
            new WebPermission(NetworkAccess.Connect, uriString).Demand();
        }
    }

    private static string UriToString(Uri uri)
    {
        if (uri == null)
        {
            throw new ArgumentNullException(nameof(uri));
        }

        UriComponents components = (uri.IsAbsoluteUri ? UriComponents.AbsoluteUri : UriComponents.SerializationInfoString);
        return new StringBuilder(uri.GetComponents(components, UriFormat.SafeUnescaped), 2083).ToString();
    }
}
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
c#
                                
using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;

internal sealed class NativeMethods
{
    #region enums  

    public enum ErrorFlags
    {
        ERROR_INSUFFICIENT_BUFFER = 122,
        ERROR_INVALID_PARAMETER = 87,
        ERROR_NO_MORE_ITEMS = 259
    }

    public enum InternetFlags
    {
        INTERNET_COOKIE_HTTPONLY = 8192, //Requires IE 8 or higher  
        INTERNET_COOKIE_THIRD_PARTY = 131072,
        INTERNET_FLAG_RESTRICTED_ZONE = 16
    }

    #endregion

    #region DLL Imports  

    [SuppressUnmanagedCodeSecurity, SecurityCritical, DllImport("wininet.dll", EntryPoint = "InternetGetCookieExW", CharSet = CharSet.Unicode, SetLastError = true, ExactSpelling = true)]
    internal static extern bool InternetGetCookieEx([In] string Url, [In] string cookieName, [Out] StringBuilder cookieData, [In, Out] ref uint pchCookieData, uint flags, IntPtr reserved);

    #endregion
}
1234567891011121314151617181920212223242526272829303132

使用获取cookie

c#
 
FullWebBrowserCookie.GetCookieInternal(Browser.Source, false)
1
点击查看全文
0 3261 0