List icon 目录

从 1.x 迁移到 2.0

DotNetBrowser 2.0 版本对库的内部功能和公共 API 进行了重大改进。 本指南介绍了如何使使用 DotNetBrowser 1.x 版本编写的应用程序代码与 2.0 版本兼容。

概述

为什么要迁移?

我们建议您将代码更新到最新版本,因为所有新功能、Chromium 升级、对新操作系统和 .NET Framework 版本的支持、错误修复、安全补丁、性能和内存使用的增强都会应用到最新版本之上。

需要多长时间?

根据我们的经验,升级到一个新的主要版本可能需要几个小时到几天的时间,这取决于您在应用程序中使用的功能数量。跟以往一样,我们强烈建议在完成升级后,在软件支持的所有环境中测试软件。

获取帮助

请查看本指南末尾的常见问题部分。或许您可以在这里找到答案。

如果您在本指南中未找到所需答案,且在迁移过程中需要帮助,请联系我们。我们将竭诚为您提供帮助。

主要变更

API 和架构

在 DotNetBrowser 2.0 版本中,该库的架构得到了改进。现在,DotNetBrowser 允许您创建两个完全独立的 IBrowser 实例,并控制其生命周期。随着内部架构的变化,公共 API 也得到了改进,并通过新功能进行了扩展。

请参阅映射部分,了解 1.x 版本的主要功能如何映射到 2.0 版本。

系统要求

从该版本开始,DotNetBrowser 不再支持 .NET Framework 4.0。当前的系统要求请参阅此处

程序集

库的结构已更改。现在,该库由以下程序集组成:

  • DotNetBrowser.dll — 数据类和接口;
  • DotNetBrowser.Core.dll — 核心实现;
  • DotNetBrowser.Logging.dll — DotNetBrowser Logging API 实现;
  • DotNetBrowser.WinForms.dll — 用于嵌入 WinForms 应用程序的类和接口;
  • DotNetBrowser.Wpf.dll — 用于嵌入 WPF 应用程序的类和接口;
  • DotNetBrowser.Chromium.Win-x86.dll — 适用于 Windows 的 Chromium 32 位二进制文件;
  • DotNetBrowser.Chromium.Win-x64.dll — 适用于 Windows 的 Chromium 64 位二进制文件。

基本概念

在新的 API 中,创建和释放各种对象的方式发生了变化。

要创建 IEngine 对象,请使用 EngineFactory.Create() 静态方法:

IEngine engine = EngineFactory.Create(options);
Dim engine As IEngine = EngineFactory.Create(options)

要创建不可变数据对象,请使用 <Object>.Builder.Build() 方法:

EngineOptions engineOptions = new EngineOptions.Builder()
{
    Language = Language.EnglishUs
}.Build();
Dim engineOptions As EngineOptions = New EngineOptions.Builder() With {
    .Language = Language.EnglishUs
}.Build()

每个应手动释放的对象都实现了 IDisposable 接口,例如,IBrowser。要释放该对象,请调用 IDisposable.Dispose() 方法:

browser.Dispose();
browser.Dispose()

某些服务对象依赖于其他服务对象。当您释放某个服务对象时,所有依赖于该对象的服务对象都将自动释放,因此您无需手动释放它们。有关关键对象及其交互原理的详细信息,请参阅架构指南。

处理程序

处理程序用于处理来自 Chromium 引擎的各种回调,并修改其行为。

v1.x

在 DotNetBrowser 1.x 版本中,处理程序通常作为接口类型的属性来实现,例如 PrintHandlerPermissionHandlerLoadHandler 等。

v2.0

在 DotNetBrowser 2.0 版中,所有处理程序都是以 IHandler<in T>IHandler<in T, out TResult>类型的属性实现的,其中 T 是参数类型,TResult 是结果类型。从处理程序返回的结果将用于通知 Chromium 引擎并影响其行为。

要注册和注销处理程序,请使用相应的属性设置器和获取器。

IHandler<in T, out TResult> 接口有以下默认实现:

  • Handler<T, TResult> 类允许封装 lambda 和方法组;
  • AsyncHandler<T, TResult> 类允许封装 async lambdas 和方法组,或返回 Task<TResult>的 lambdas 和方法组。

在某些情况下,引擎似乎会在处理程序返回结果之前出现阻塞。在使用 AsyncHandler 的情况下,引擎似乎会在返回的任务中的结果可用之前出现阻塞。

线程安全

该库不是线程安全的,因此请避免同时从不同线程中使用该库。

许可

在 DotNetBrowser 2.0 版本中,许可证格式以及库检查许可证的方式已经得到了改进。

v1.x

在之前的版本中,许可证是一个名为 teamdev.licenses 的文本文件。该文本文件包含了许可证的纯文本。要设置该许可证,您必须将此文本文件作为 EmbeddedResource 包含在项目中,或将其复制到 .NET 应用程序的工作目录中。

项目许可证与完全限定类型名称绑定(例如,Company.Product.MyClass)。它可以是您应用程序中的任何类。唯一的要求是,该类必须包含在您使用 DotNetBrowser 的 .NET 应用程序的类路径中。

v2.0

现在,该库需要一个许可证密钥,该密钥是一个包含字母和数字组合的字符串。您可以通过 API 将许可证添加到您的项目中

也可以将此字符串放入名为 dotnetbrowser.license 的文本文件中,然后将这个文本文件作为 EmbeddedResource 包含在您的项目中,或将其复制到 .NET 应用程序的工作目录中。

现在,项目许可证与命名空间绑定。命名空间应采用 Company.Product.Namespace 格式。它应该是创建 IEngine 实例的类的顶级命名空间。

例如,如果项目许可证与 Company.Product 命名空间绑定,则您只能在位于该命名空间或其内部命名空间的类中创建 IEngine 实例,例如 Company.Product.Namespace

IEngine 是在 DotNetBrowser 2 中引入的。我们建议您查看指南,其中介绍了新架构、如何创建 IEngine 和管理多个 IBrowser的生命周期。

您可以使用已创建的 IEngine 实例,并从位于其他命名空间的类中调用库的 API,而不受任何限制。

删除的功能

从该版本开始,DotNetBrowser 不再支持 .NET Framework 4。

新版本暂时删除了以下功能:

我们将在下一个版本中提供上述功能的替代方案。

映射

在本节中,我们将介绍 DotNetBrowser 1.x 版本的主要功能如何映射到 2.0 版本。

Engine

创建 Engine

1.x

IEngine 不是公共 API 的一部分。它是在应用程序中创建第一个 Browser 实例时在内部创建的。应用程序中只能创建和使用一个 IEngine

2.0

IEngine 现在是公共 API 的一部分。您可以在应用程序中创建和使用多个 Engine 实例。要使用所需选项创建 Engine 实例,请使用下面的代码示例:

IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
    // 默认错误页面和图形用户界面使用的语言。
    Language = Language.EnglishUs,
    // 储存诸如缓存、cookie、历史记录、 
    // GPU 缓存、本地存储、访问过的链接、
    // 网页数据、拼写检查词典文件等
    // 数据的目录的绝对路径。
    UserDataDirectory = @"C:\Users\Me\DotNetBrowser"
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With {
    ' 默认错误页面和图形用户界面使用的语言。
    Language = Language.EnglishUs,
    ' 储存诸如缓存、cookie、历史记录、 
    ' GPU 缓存、本地存储、访问过的链接、
    ' 网页数据、拼写检查词典文件等
    ' 数据的目录的绝对路径。
    .UserDataDirectory = "C:\Users\Me\DotNetBrowser"
}.Build())

每个 IEngine 实例都会运行一个单独的本地进程,在该进程中创建并初始化带有所提供选项的 Chromium。本地进程通过进程间通信(IPC)桥与 .NET 进程通信。如果本地进程因崩溃而意外终止,.NET 进程将继续运行。

您可以使用以下通知来了解 IEngine 意外终止的时间,以便重新创建引擎并恢复 IBrowser 实例:

engine.Disposed += (s, e) => 
{
    long exitCode = e.ExitCode;
    if(exitCode != 0)
    {
        // 清除所有分配的资源并重新创建 Engine。
    }
};
AddHandler engine.Disposed, Sub(s, e)
    Dim exitCode As Long = e.ExitCode
    If exitCode <> 0 Then
        ' 清除所有分配的资源并重新创建 Engine。
    End If
End Sub

关闭 Engine

1.x

当应用程序中的最后一个 Browser 实例被处理时,IEngine 会被自动处理。

2.0

当不再需要 IEngine 时,应使用 Dispose() 方法手动处理它:

engine.Dispose();
engine.Dispose()

IEngine 被处理时,它的所有 IBrowser 实例会被自动处理。任何使用已处理 IEngine 的尝试都会导致异常。

要了解 IEngine 的处理时间,请使用以下事件:

engine.Disposed += (s, e) => {};
AddHandler engine.Disposed, Sub(s, e)
End Sub

Browser

创建 Browser

1.x

Browser browser = BrowserFactory.Create();
Dim browser As Browser = BrowserFactory.Create()

2.0

IBrowser browser = engine.CreateBrowser();
Dim browser As IBrowser = engine.CreateBrowser()

创建带选项的 Browser

1.x

BrowserContextParams parameters = new BrowserContextParams(@"C:\Users\Me\DotNetBrowser") 
{ 
    StorageType = StorageType.MEMORY 
};
BrowserContext context = new BrowserContext(parameters);
Browser browser = BrowserFactory.Create(context, BrowserType.LIGHTWEIGHT);
Dim parameters As BrowserContextParams = 
    New BrowserContextParams("C:\Users\Me\DotNetBrowser") With {
        .StorageType = StorageType.MEMORY
    }
Dim context As BrowserContext = New BrowserContext(parameters)
Dim browser As Browser = BrowserFactory.Create(context, BrowserType.LIGHTWEIGHT)

2.0

BrowserContext 功能已移至 IEngine。因此,应将相同的代码替换为下面的代码示例:

IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
    IncognitoEnabled = true,
    RenderingMode = RenderingMode.OffScreen,
    UserDataDirectory = @"C:\Users\Me\DotNetBrowser"
}.Build());
IBrowser browser = engine.CreateBrowser();
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With {
    .IncognitoEnabled = True,
    .RenderingMode = RenderingMode.OffScreen,
    .UserDataDirectory = "C:\Users\Me\DotNetBrowser"
}.Build())
Dim browser As IBrowser = engine.CreateBrowser()

处理 Browser

1.x

browser.Dispose();
browser.Dispose()

2.0

browser.Dispose();
browser.Dispose()

响应/不响应

1.x

browser.RenderResponsiveEvent += (s, e ) => {};
browser.RenderUnresponsiveEvent += (s, e) => {};
AddHandler browser.RenderResponsiveEvent, Sub(s, e)
End Sub
AddHandler browser.RenderUnresponsiveEvent, Sub(s, e)
End Sub

2.0

browser.BrowserBecameResponsive += (s, e ) => {};
browser.BrowserBecameUnresponsive += (s, e) => {};
AddHandler browser.BrowserBecameResponsive, Sub(s, e)
End Sub
AddHandler browser.BrowserBecameUnresponsive, Sub(s, e)
End Sub

BrowserView

在 DotNetBrowser 1.x 版本中,使用默认构造函数创建 BrowserView 会导致在同一线程中初始化绑定的 Browser 实例。因此,在 Browser 实例创建和初始化之前,UI 主线程可能会出现阻塞,而这可能需要相当长的时间。

在 DotNetBrowser 2.0 版本中,使用默认构造函数创建 IBrowserView 实现时,创建的 UI 控件最初不会绑定到任何浏览器。与特定 IBrowser 实例的连接是在必要时通过调用 InitializeFrom(IBrowser) 扩展方法来建立的。

当应用程序关闭时,IBrowserView 实现不会处理已连接的 IBrowserIEngine 实例。 因此,即使关闭了所有应用程序窗口,浏览器和引擎也会继续运行,并阻止应用程序终止。要解决这种情况,请在应用程序关闭时处理 IBrowserIEngine 实例。

创建 WinForms BrowserView

1.x

using DotNetBrowser.WinForms;
// ...
BrowserView view = new WinFormsBrowserView();
Imports DotNetBrowser.WinForms
' ...
Dim view As BrowserView = New WinFormsBrowserView()

2.0

using DotNetBrowser.WinForms;
// ...
BrowserView view = new BrowserView();
view.InitializeFrom(browser);
Imports DotNetBrowser.WinForms
' ...
Dim view As BrowserView = New BrowserView()
view.InitializeFrom(browser)

创建 WPF BrowserView

1.x

using DotNetBrowser.WPF;
// ...
BrowserView view = new WPFBrowserView(browser);
Imports DotNetBrowser.WPF
' ...
Dim view As BrowserView = New WPFBrowserView()

2.0

using DotNetBrowser.Wpf;
// ...
BrowserView view = new BrowserView();
view.InitializeFrom(browser);
Imports DotNetBrowser.Wpf
' ...
Dim view As BrowserView = New BrowserView()
view.InitializeFrom(browser)

Frame

使用 Frame

1.x

网页可能由主框架和多个子框架组成。要执行与框架相关的操作,请将框架的标识符传递给相应的方法:

// 获取主框架的 HTML。
browser.GetHTML();

// 获取所有框架的 HTML。
foreach (long frameId in browser.GetFramesIds()) {
    string html = browser.GetHTML(frameId);
}
' 获取主框架的 HTML。
browser.GetHTML()

' 获取所有框架的 HTML。
For Each frameId As Long In browser.GetFramesIds()
    Dim html As String = browser.GetHTML(frameId)
Next

2.0

IFrame 现在是公共 API 的一部分。您可以通过 IFrame 实例处理框架:

// 获取主框架的 HTML。
string html = browser.MainFrame?.Html;

// 获取所有框架的 HTML。
foreach (IFrame frame in browser.AllFrames)
{
    string html = frame.Html;
}
' 获取主框架的 HTML。
Dim html As String = browser.MainFrame?.Html

' 获取所有框架的 HTML。
For Each frame As IFrame In browser.AllFrames
    Dim html As String = frame.Html
Next

导航

加载 URL

1.x

browser.LoadURL("https://www.google.com");
browser.LoadURL("https://www.google.com")

2.0

browser.Navigation.LoadUrl("https://www.google.com");
browser.Navigation.LoadUrl("https://www.google.com")

加载 HTML

1.x

browser.LoadHTML("<html><body></body></html>");
browser.LoadHTML("<html><body></body></html>")

2.0

browser.MainFrame?.LoadHtml("<html><body></body></html>"));
browser.MainFrame?.LoadHtml("<html><body></body></html>"))

导航事件

开始加载

1.x

browser.StartLoadingFrameEvent += (s, e) =>
{
    string url = e.ValidatedURL;
};
AddHandler browser.StartLoadingFrameEvent, Sub(s, e)
    Dim url As String = e.ValidatedURL
End Sub

2.0

browser.Navigation.NavigationStarted += (s, e) => 
{
    string url = e.Url;
};
AddHandler browser.Navigation.NavigationStarted, Sub(s, e)
    Dim url As String = e.Url
End Sub

完成加载

1.x

browser.FinishLoadingFrameEvent+= (s, e) =>
{
    string html = browser.GetHTML(e.FrameId);
};
AddHandler browser.FinishLoadingFrameEvent, Sub(s, e)
    Dim html As String = browser.GetHTML(e.FrameId)
End Sub

2.0

browser.Navigation.FrameLoadFinished += (s, e) =>
{
    string html = e.Frame.Html;
};
AddHandler browser.Navigation.FrameLoadFinished, Sub(s, e)
    Dim html As String = e.Frame.Html
End Sub

加载失败

1.x

browser.FailLoadingFrameEvent  += (s, e) => 
{
    NetError errorCode = e.ErrorCode;
};
AddHandler browser.FailLoadingFrameEvent, Sub(s, e)
    Dim errorCode As NetError = e.ErrorCode
End Sub

2.0

browser.Navigation.FrameLoadFailed += (s, e) => 
{
    NetError error = e.ErrorCode;
};
AddHandler browser.Navigation.FrameLoadFailed, Sub(s, e)
    Dim errorCode As NetError = e.ErrorCode
End Sub

browser.Navigation.NavigationFinished += (s, e) => 
{
    NetError error = e.ErrorCode;
};
AddHandler browser.Navigation.NavigationFinished, Sub(s, e)
    Dim errorCode As NetError = e.ErrorCode
End Sub

网络

配置用户代理

1.x

BrowserPreferences.SetUserAgent("My User-Agent");
BrowserPreferences.SetUserAgent("My User-Agent")

2.0

IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
    UserAgent = "My User-Agent"
}
.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With {
    .UserAgent = "My User-Agent"
}.Build())

配置 Accept-Language

1.x

browserContext.AcceptLanguage = "fr, en-gb;q=0.8, en;q=0.7";
browserContext.AcceptLanguage = "fr, en-gb;q=0.8, en;q=0.7"

2.0

engine.Network.AcceptLanguage = "fr, en-gb;q=0.8, en;q=0.7";
engine.Network.AcceptLanguage = "fr, en-gb;q=0.8, en;q=0.7"

配置代理

1.x

ProxyConfig proxyConfig = browserContext.ProxyConfig;
browserContext.ProxyConfig = new CustomProxyConfig("http-proxy-server:80");
Dim proxyConfig As ProxyConfig = browserContext.ProxyConfig
browserContext.ProxyConfig = New CustomProxyConfig("http-proxy-server:80")

2.0

engine.Proxy.Settings = new CustomProxySettings("http-proxy-server:80");
engine.Proxy.Settings = New CustomProxySettings("http-proxy-server:80")

重定向 URL 请求

1.x

class MyNetworkDelegate : DefaultNetworkDelegate
{
    public override void OnBeforeURLRequest(BeforeURLRequestParams parameters)
    {
        parameters.SetURL("https://www.google.com");
    }
}
// ...
browserContext.NetworkService.NetworkDelegate = new MyNetworkDelegate();
Class MyNetworkDelegate
    Inherits DefaultNetworkDelegate

    Public Overrides Sub OnBeforeURLRequest(ByVal parameters As BeforeURLRequestParams)
        parameters.SetURL("https://www.google.com")
    End Sub
End Class
' ...
browserContext.NetworkService.NetworkDelegate = New MyNetworkDelegate()

2.0

engine.Network.SendUrlRequestHandler =
    new Handler<SendUrlRequestParameters, SendUrlRequestResponse>((e) =>
    {
        return SendUrlRequestResponse.Override("https://www.google.com");
    });
engine.Network.SendUrlRequestHandler =
        New Handler(Of SendUrlRequestParameters, SendUrlRequestResponse)(
            Function(e) SendUrlRequestResponse.Override("https://www.google.com"))

覆盖 HTTP 标头

1.x

class MyNetworkDelegate : DefaultNetworkDelegate
{
    public override void OnBeforeSendHeaders(BeforeSendHeadersParams parameters)
    {
        HttpHeadersEx headers = params.HeadersEx;
        headers.SetHeader("User-Agent", "MyUserAgent");
        headers.SetHeader("Content-Type", "text/html");
    }
}
// ...
browserContext.NetworkService.NetworkDelegate = new MyNetworkDelegate();
Class MyNetworkDelegate
    Inherits DefaultNetworkDelegate

    Public Overrides Sub OnBeforeSendHeaders(parameters As BeforeSendHeadersParams)
        Dim headers As HttpHeadersEx = params.HeadersEx
        headers.SetHeader("User-Agent", "MyUserAgent")
        headers.SetHeader("Content-Type", "text/html")
    End Sub
End Class
' ...
browserContext.NetworkService.NetworkDelegate = New MyNetworkDelegate()

2.0

engine.Network.SendHeadersHandler =
    new Handler<SendHeadersParameters, SendHeadersResponse>((e) =>
    {
        return SendHeadersResponse.OverrideHeaders(new[] {
            new HttpHeader("User-Agent", "MyUserAgent"),
            new HttpHeader("Content-Type", "text/html")
        });
    });
engine.Network.SendHeadersHandler =
    New Handler(Of SendHeadersParameters, SendHeadersResponse)(
        Function(e) SendHeadersResponse.OverrideHeaders(
            {New HttpHeader("User-Agent", "MyUserAgent"),
             New HttpHeader("Content-Type", "text/html")}))

拦截 URL 请求

1.x

class MyProtocolHandler : IProtocolHandler
{
    public IUrlResponse Handle(IUrlRequest request)
    {
        string html = "<html><body><p>Hello there!</p></body></html>";
        IUrlResponse response = new UrlResponse(Encoding.UTF8.GetBytes(html));
        response.Headers.SetHeader("Content-Type", "text/html");
        return response;
    }
}
// ...
browser.Context.ProtocolService.Register("https", new MyProtocolHandler());
Class MyProtocolHandler
    Inherits IProtocolHandler

    Public Function Handle(ByVal request As IUrlRequest) As IUrlResponse
        Dim html As String = "<html><body><p>Hello there!</p></body></html>"
        Dim response As IUrlResponse = New UrlResponse(Encoding.UTF8.GetBytes(html))
        response.Headers.SetHeader("Content-Type", "text/html")
        Return response
    End Function
End Class
' ...
browser.Context.ProtocolService.Register("https", New MyProtocolHandler())

2.0

network.InterceptRequestHandler =
    new Handler<InterceptRequestParameters, InterceptRequestResponse>(p =>
    {
        if (!p.UrlRequest.Url.StartsWith("https"))
        {
            return InterceptRequestResponse.Proceed();
        }

        UrlRequestJobOptions options = new UrlRequestJobOptions
        {
            Headers = new List<HttpHeader>
            {
                new HttpHeader("Content-Type", "text/plain"),
                new HttpHeader("Content-Type", "charset=utf-8")
            }
        };
        UrlRequestJob job = network.CreateUrlRequestJob(p.UrlRequest, options);

        Task.Run(() =>
        {
            // 请求处理在后台线程中执行,
            // 以避免冻结网页。
            string html = "<html><body><p>Hello there!</p></body></html>";
            job.Write(Encoding.UTF8.GetBytes(html));
            job.Complete();
        });
        
        return InterceptRequestResponse.Intercept(job);
    });
network.InterceptRequestHandler =
    New Handler(Of InterceptRequestParameters, InterceptRequestResponse)(Function(p)
        If Not p.UrlRequest.Url.StartsWith("https") Then
            Return InterceptRequestResponse.Proceed()
        End If

        Dim options = New UrlRequestJobOptions With {
                .Headers = New List(Of HttpHeader) From {
                New HttpHeader("Content-Type", "text/plain"),
                New HttpHeader("Content-Type", "charset=utf-8")
                }
                }
        Dim job As UrlRequestJob = network.CreateUrlRequestJob(p.UrlRequest, options)
        Task.Run(Sub()
            ' 请求处理在后台线程中执行,
            ' 以避免冻结网页。
            Dim html = "<html><body><p>Hello 
there!</p></body></html>"
            job.Write(Encoding.UTF8.GetBytes(html))
            job.Complete()
        End Sub)
        Return InterceptRequestResponse.Intercept(job)
    End Function)

身份验证

Proxy、Basic、Digest、NTLM

1.x

class MyNetworkDelegate : DefaultNetworkDelegate
{
    public override bool OnAuthRequired(AuthRequiredParams params)
    {
        if(params.IsProxy)
        {
            params.Username = "user";
            params.Password = "password";
            return false;
        }
        // 取消身份验证请求。
        return true;
    }
}
// ...
browserContext.NetworkService.NetworkDelegate = new MyNetworkDelegate();
Class MyNetworkDelegate
    Inherits DefaultNetworkDelegate

    Public Overrides Function OnAuthRequired(ByVal params As AuthRequiredParams) As Boolean
        If params.IsProxy Then
            params.Username = "user"
            params.Password = "password"
            Return False
        End If
        ' 取消身份验证请求。
        Return True
    End Function
End Class
' ...
browserContext.NetworkService.NetworkDelegate = New MyNetworkDelegate()

2.0

engine.Network.AuthenticateHandler =
    new Handler<AuthenticateParameters, AuthenticateResponse>((p) =>
    {
        if (p.IsProxy)
        {
            return AuthenticateResponse.Continue("user", "password");
        }
        else
        {
            return AuthenticateResponse.Cancel();
        }
    });
engine.Network.AuthenticateHandler =
    New Handler(Of AuthenticateParameters, AuthenticateResponse)(Function(p)
        If p.IsProxy Then
            Return AuthenticateResponse.Continue("user", "password")
        Else
            Return AuthenticateResponse.Cancel()
        End If
    End Function)

HTTPS 客户端证书

1.x

class MyDialogHandler : DialogHandler
{
    public CloseStatus OnSelectCertificate(CertificatesDialogParams parameters)
    {
        List<Certificate> certificates = parameters.Certificates;
        if (certificates.Count == 0) {
            return CloseStatus.CANCEL;
        } else {
            parameters.SelectedCertificate = certificates.LastOrDefault();
            return CloseStatus.OK;
        }
    }

    // ...
}
// ...
browser.DialogHandler = new MyDialogHandler();
Class MyDialogHandler
    Inherits DialogHandler

    Public Function OnSelectCertificate(parameters As CertificatesDialogParams) As CloseStatus
        Dim certificates As List(Of Certificate) = parameters.Certificates

        If certificates.Count Is 0 Then
            Return CloseStatus.CANCEL
        Else
            parameters.SelectedCertificate = certificates.LastOrDefault()
            Return CloseStatus.OK
        End If
    End Function
    ' ...
End Class
' ...
browser.DialogHandler = New MyDialogHandler()

2.0

browser.SelectCertificateHandler
    = new Handler<SelectCertificateParameters, SelectCertificateResponse>(p =>
    {
        int count = p.Certificates.Count();
        return count == 0 ?
            SelectCertificateResponse.Cancel() :
            SelectCertificateResponse.Select(p.Certificates.Count() - 1);
    });
browser.SelectCertificateHandler =
    New Handler(Of SelectCertificateParameters, SelectCertificateResponse)(Function(p)
        Dim count As Integer = p.Certificates.Count()
        Return If (count = 0,
                   SelectCertificateResponse.Cancel(),
                   SelectCertificateResponse.Select(p.Certificates.Count() - 1))
    End Function)

插件

过滤插件

1.x

class MyPluginFilter : PluginFilter
{
    public bool IsPluginAllowed(PluginInfo pluginInfo)
    {
        return true;
    }
}
// ...
browser.PluginManager.PluginFilter = new MyPluginFilter();
Class MyPluginFilter
    Inherits PluginFilter

    Public Function IsPluginAllowed(ByVal pluginInfo As PluginInfo) As Boolean
        Return True
    End Function
End Class
' ...
browser.PluginManager.PluginFilter = New MyPluginFilter()

2.0

engine.Plugins.AllowPluginHandler = 
    new Handler<AllowPluginParameters, AllowPluginResponse>(p =>
    {
        return AllowPluginResponse.Allow();
    });
engine.Plugins.AllowPluginHandler =
    New Handler(Of AllowPluginParameters, AllowPluginResponse)(
        Function(p) AllowPluginResponse.Allow())

DOM

访问文档

1.x

DOMDocument document = browser.GetDocument();
Dim document As DOMDocument = browser.GetDocument()

2.0

IDocument document = browser.MainFrame?.Document;
Dim document As IDocument = browser.MainFrame?.Document

DOM 事件

处理事件

1.x

element.AddEventListener(DOMEventType.OnClick, (s, e) =>
{
    DOMEventTarget eventTarget = e.Target;
    if (eventTarget != null) {
        // ...
    }
}, false);
element.AddEventListener(DOMEventType.OnClick, Sub(s, e)
    Dim eventTarget As DOMEventTarget = e.Target

    If eventTarget IsNot Nothing Then
        ' ...
    End If
End Sub, False)

2.0

element.Events.Click += (s, e) =>
{
    IEventTarget eventTarget = e.Event.Target;
    if (eventTarget != null)
    {
        // ...
    }
};
AddHandler element.Events.Click, Sub(s, e)
    Dim eventTarget As IEventTarget = e.Event.Target

    If eventTarget IsNot Nothing Then
        ' ...
    End If
End Sub

JavaScript

从 .NET 调用 JavaScript

1.x

string name = browser.ExecuteJavaScriptAndReturnValue("'Hello'")
        .AsString().Value;
double number = browser.ExecuteJavaScriptAndReturnValue("123")
        .AsNumber().Value;
bool flag = browser.ExecuteJavaScriptAndReturnValue("true")
        .AsBoolean().Value;
JSObject window = browser.ExecuteJavaScriptAndReturnValue("window")
        .AsObject();
Dim name As String = browser.ExecuteJavaScriptAndReturnValue("'Hello'") _
        .AsString().Value
Dim number As Double = browser.ExecuteJavaScriptAndReturnValue("123") _
        .AsNumber().Value
Dim flag As Boolean = browser.ExecuteJavaScriptAndReturnValue("true") _
        .AsBoolean().Value
Dim window As JSObject = browser.ExecuteJavaScriptAndReturnValue("window") _
        .AsObject()

2.0

JSValue 类已在 DotNetBrowser 2.0 中删除。现在类型转换已自动完成。您既可以同步阻塞当前线程的执行,也可以异步执行 JavaScript:

IFrame mainFrame = browser.MainFrame;
if(mainFrame != null)
{
    // 使用 await 执行。
    string name = await mainFrame.ExecuteJavaScript<string>("'Hello'");
    double number = await mainFrame.ExecuteJavaScript<double>("123");
    bool flag = await mainFrame.ExecuteJavaScript<bool>("true");
    IJsObject window = await mainFrame.ExecuteJavaScript<IJsObject>("window");

    // 同步执行会阻塞当前线程。
    name = mainFrame.ExecuteJavaScript<string>("'Hello'").Result;
    number = mainFrame.ExecuteJavaScript<double>("123").Result;
    flag = mainFrame.ExecuteJavaScript<bool>("true").Result;
    window = mainFrame.ExecuteJavaScript<IJsObject>("window").Result;

    // 异步执行并延续。
    mainFrame.ExecuteJavaScript<IDocument>("document").ContinueWith(t =>{
        string baseUri = t.Result.BaseUri;
    });
}
Dim mainFrame As IFrame = browser.MainFrame

If mainFrame IsNot Nothing Then
    ' 使用 await 执行。
    Dim name As String = Await mainFrame.ExecuteJavaScript (Of String)("'Hello'")
    Dim number As Double = Await mainFrame.ExecuteJavaScript (Of Double)("123")
    Dim flag As Boolean = Await mainFrame.ExecuteJavaScript (Of Boolean)("true")
    Dim window As IJsObject = Await mainFrame.ExecuteJavaScript (Of IJsObject)("window")

    ' 同步执行会阻塞当前线程。
    name = mainFrame.ExecuteJavaScript (Of String)("'Hello'").Result
    number = mainFrame.ExecuteJavaScript (Of Double)("123").Result
    flag = mainFrame.ExecuteJavaScript (Of Boolean)("true").Result
    window = mainFrame.ExecuteJavaScript (Of IJsObject)("window").Result

    ' 异步执行并延续。
    mainFrame.ExecuteJavaScript (Of IDocument)("document").ContinueWith(
        Sub(t)
            Dim baseUri As String = t.Result.BaseUri
        End Sub)
End If

从 JavaScript 调用 .NET

1.x

在 .NET 代码中:

public class MyObject {
    public void foo(string text) {}
}
// ...
JSValue window = browser.ExecuteJavaScriptAndReturnValue("window");
if (window.IsObject()) {
    window.AsObject().SetProperty("myObject", new MyObject());
}
Public Class MyObject
    Public Sub foo(text As String)
    End Sub
End Class
' ...
Dim window As JSValue = browser.ExecuteJavaScriptAndReturnValue("window")

If window.IsObject() Then
    window.AsObject().SetProperty("myObject", New MyObject())
End If

在 JavaScript 代码中:

window.myObject.foo("Hello");

2.0

在 .NET 代码中:

public class MyObject {
    public void foo(string text) {}
}
// ...
IJsObject window = frame.ExecuteJavaScript<IJsObject>("window").Result;
window.Properties["myObject"] = new MyObject();
Public Class MyObject
    Public Sub foo(text As String)
    End Sub
End Class
' ...
Dim window As IJsObject = frame.ExecuteJavaScript(Of IJsObject)("window").Result
window.Properties("myObject") = New MyObject()

在 JavaScript 代码中:

window.myObject.foo("Hello");

注入 JavaScript

1.x

browser.ScriptContextCreated += (sender, args) =>
{
    JSValue window = browser.ExecuteJavaScriptAndReturnValue(args.Context.FrameId, @"window");
    window.AsObject().SetProperty("myObject", new MyObject());
};
AddHandler browser.ScriptContextCreated, Sub(sender, args)
    Dim window As JSValue = 
        browser.ExecuteJavaScriptAndReturnValue(args.Context.FrameId, "window")
    window.AsObject().SetProperty("myObject", New MyObject())
End Sub

2.0

browser.InjectJsHandler = new Handler<InjectJsParameters>((args) => 
{
    IJsObject window = args.Frame.ExecuteJavaScript<IJsObject>("window").Result;
    window.Properties["myObject"] = new MyObject();
});
browser.InjectJsHandler = New Handler(Of InjectJsParameters)(Sub(args)
    Dim window As IJsObject = args.Frame.ExecuteJavaScript (Of IJsObject)("window").Result
    window.Properties("myObject") = New MyObject()
End Sub)

控制台事件

1.x

browser.ConsoleMessageEvent += (s, args) =>
{
    string message = args.Message;
};
AddHandler browser.ConsoleMessageEvent, Sub(s, args)
    Dim message As String = args.Message
End Sub

2.0

browser.ConsoleMessageReceived += (s, args) =>
{
    string message = args.Message;
};
AddHandler browser.ConsoleMessageReceived, Sub(s, args)
    Dim message As String = args.Message
End Sub

弹出窗口

抑制弹出窗口

1.x

class MyPopupHandler : PopupHandler
{
    public PopupContainer HandlePopup(PopupParams popupParams)
    {
        return null;
    }
}
// ...
browser.PopupHandler = new MyPopupHandler();
 Class MyPopupHandler
    Inherits PopupHandler

    Public Function HandlePopup(ByVal popupParams As PopupParams) As PopupContainer
        Return Nothing
    End Function
End Class
' ...
browser.PopupHandler = New MyPopupHandler()

2.0

browser.CreatePopupHandler = new Handler<CreatePopupParameters, CreatePopupResponse>((p) =>
{
    return CreatePopupResponse.Suppress();
});
browser.CreatePopupHandler =
    New Handler(Of CreatePopupParameters, CreatePopupResponse)(
        Function(p) CreatePopupResponse.Suppress())

打开弹出窗口

1.x

class MyPopupContainer : PopupContainer
{
    public void InsertBrowser(Browser browser, System.Drawing.Rectangle initialBounds)
    {
        // ...
    }
}
class MyPopupHandler : PopupHandler
{
    public PopupContainer HandlePopup(PopupParams popupParams)
    {
        return new MyPopupContainer();
    }
}
// ...
browser.PopupHandler = new MyPopupHandler();
Class MyPopupContainer
    Inherits PopupContainer

    Public Sub InsertBrowser(browser As Browser, initialBounds As Rectangle)
    ' ...
    End Sub
End Class

Class MyPopupHandler
    Inherits PopupHandler

    Public Function HandlePopup(popupParams As PopupParams) As PopupContainer
        Return New MyPopupContainer()
    End Function
End Class
' ...
browser.PopupHandler = New MyPopupHandler()

2.0

browser.CreatePopupHandler = new Handler<CreatePopupParameters, CreatePopupResponse>((p) =>
{
    return CreatePopupResponse.Create();
});
browser.OpenPopupHandler = new Handler<OpenPopupParameters>((p) =>
{
    IBrowser popup = p.PopupBrowser;
    // ...
});
browser.CreatePopupHandler =
    New Handler(Of CreatePopupParameters, CreatePopupResponse)(
        Function(p) CreatePopupResponse.Create())

browser.OpenPopupHandler = New Handler(Of OpenPopupParameters)(
    Sub(p)
        Dim popup As IBrowser = p.PopupBrowser
        ' ...
    End Sub)

对话框

JavaScript 对话框

1.x

class MyDialogHandler : DialogHandler
{
    public void OnAlert(DialogParams parameters) 
    {
    }

    public CloseStatus OnConfirmation(DialogParams parameters) 
    {
        return CloseStatus.CANCEL;
    }

    public CloseStatus OnPrompt(PromptDialogParams parameters) 
    {
        parameters.PromptText = "Text";
        return CloseStatus.OK;
    }
    // ...
}
// ...
browser.DialogHandler = new MyDialogHandler();
Class MyDialogHandler
    Inherits DialogHandler
    Public  Sub OnAlert(ByVal parameters As DialogParams)
    End Sub
 
    Public Function OnConfirmation(ByVal parameters As DialogParams) As CloseStatus
        Return CloseStatus.CANCEL
    End Function
 
    Public Function OnPrompt(ByVal parameters As PromptDialogParams) As CloseStatus
        parameters.PromptText = "Text"
        Return CloseStatus.OK
    End Function
    ' ...
End Class
' ...
browser.DialogHandler = New MyDialogHandler()

2.0

browser.JsDialogs.AlertHandler = new Handler<AlertParameters>(p =>
    {
        // ...
    });
browser.JsDialogs.ConfirmHandler =
    new Handler<ConfirmParameters, ConfirmResponse>(p => 
    {
        return ConfirmResponse.Cancel();
    });
browser.JsDialogs.PromptHandler =
    new Handler<PromptParameters, PromptResponse>(p =>
    {
        return PromptResponse.SubmitText("responseText");
    });
browser.JsDialogs.AlertHandler = New Handler(Of AlertParameters)(
    Sub(p)
        ' ...
    End Sub)
browser.JsDialogs.ConfirmHandler =
    New Handler(Of ConfirmParameters, ConfirmResponse)(
        Function(p) ConfirmResponse.Cancel())
browser.JsDialogs.PromptHandler =
    New Handler(Of PromptParameters, PromptResponse)(
        Function(p) PromptResponse.SubmitText("responseText"))

文件对话框

1.x

class FileChooserHandler : DialogHandler
{
    public CloseStatus OnFileChooser(FileChooserParams parameters) {
        FileChooserMode mode = parameters.Mode;
        if (mode == FileChooserMode.Open) {
            parameters.SelectedFiles = "file1.txt";
        }
        if (mode == FileChooserMode.OpenMultiple) {
            string[] selectedFiles = {"file1.txt", "file2.txt"};
            parameters.SelectedFiles = string.Join("|", selectedFiles);
        }
        return CloseStatus.OK;
    }
    // ...
}
// ...
browser.DialogHandler = new FileChooserHandler();
Class FileChooserHandler
    Inherits DialogHandler

    Public Function OnFileChooser(parameters As FileChooserParams) As CloseStatus
        Dim mode As FileChooserMode = parameters.Mode

        If mode Is FileChooserMode.Open Then
            parameters.SelectedFiles = "file1.txt"
        End If

        If mode Is FileChooserMode.OpenMultiple Then
            Dim selectedFiles As String() = {"file1.txt", "file2.txt"}
            parameters.SelectedFiles = String.Join("|", selectedFiles)
        End If

        Return CloseStatus.OK
    End Function
    ' ...
End Class
' ...
browser.DialogHandler = New FileChooserHandler()

2.0

browser.Dialogs.OpenFileHandler =
    new Handler<OpenFileParameters, OpenFileResponse>(p =>
    {
        return OpenFileResponse.SelectFile(Path.GetFullPath(p.DefaultFileName));
    });

browser.Dialogs.OpenMultipleFilesHandler =
    new Handler<OpenMultipleFilesParameters, OpenMultipleFilesResponse>(p =>
    {
        return OpenMultipleFilesResponse.SelectFiles(Path.GetFullPath("file1.txt"),
            Path.GetFullPath("file2.txt"));
    });
browser.Dialogs.OpenFileHandler =
    New Handler(Of OpenFileParameters, OpenFileResponse)(
        Function(p) OpenFileResponse.SelectFile(
            Path.GetFullPath(p.DefaultFileName)))

browser.Dialogs.OpenMultipleFilesHandler =
    New Handler(Of OpenMultipleFilesParameters, OpenMultipleFilesResponse)(
        Function(p) OpenMultipleFilesResponse.SelectFiles(
            Path.GetFullPath("file1.txt"),
            Path.GetFullPath("file2.txt")))

颜色对话框

1.x

class ColorDialogHandler : DialogHandler
{
    private Color color;

    public ColorDialogHandler()
    {
        color = Color.White;
    }
    
    public CloseStatus OnColorChooser(ColorChooserParams parameters)
    {        
        parameters.Color = color;
        return CloseStatus.OK;
    }
    // ...
}
// ...
browser.DialogHandler = new ColorDialogHandler();
Class ColorDialogHandler
    Inherits DialogHandler

    Private ReadOnly color As Color

    Public Sub New()
        color = Color.White
    End Sub

    Public Function OnColorChooser(parameters As ColorChooserParams) As CloseStatus
        parameters.Color = color
        Return CloseStatus.OK
    End Function
    ' ...
End Class
' ...
browser.DialogHandler = New ColorDialogHandler()

2.0

browser.Dialogs.SelectColorHandler =
    new Handler<SelectColorParameters, SelectColorResponse>(p =>
    {
        return SelectColorResponse.SelectColor(p.DefaultColor);
    });
browser.Dialogs.SelectColorHandler =
    New Handler(Of SelectColorParameters, SelectColorResponse)(
        Function(p) SelectColorResponse.SelectColor(p.DefaultColor))

SSL 证书对话框

1.x

class SelectCertificateDialogHandler : DialogHandler
{
    private const string ClientCertFile = "<cert-file>.pfx";
    private const string ClientCertPassword = "<cert-password>";
    private Certificate certificate;

    public SelectCertificateDialogHandler()
    {
        certificate = new X509Certificate2(Path.GetFullPath(ClientCertFile),
                                           ClientCertPassword,
                                           X509KeyStorageFlags.Exportable);
    }
    
    public CloseStatus OnSelectCertificate(CertificatesDialogParams parameters)
    {        
        parameters.SelectedCertificate = certificate;
        selectCertificateEvent.Set();
        return CloseStatus.OK;
    }
    // ...
}
// ...
browser.DialogHandler = new SelectCertificateDialogHandler();
Class SelectCertificateDialogHandler
    Inherits DialogHandler

    Private Const ClientCertFile As String = "<cert-file>.pfx"
    Private Const ClientCertPassword As String = "<cert-password>"
    Private certificate As Certificate

    Public Sub New()
        certificate = New X509Certificate2(Path.GetFullPath(ClientCertFile),
                                           ClientCertPassword,
                                           X509KeyStorageFlags.Exportable)
    End Sub

    Public Function OnSelectCertificate(ByVal p As CertificatesDialogParams) As CloseStatus
        p.SelectedCertificate = certificate
        selectCertificateEvent.Set()
        Return CloseStatus.OK
    End Function
    ' ...
End Class
' ...
browser.DialogHandler = New SelectCertificateDialogHandler()

2.0

string ClientCertFile = "<cert-file>.pfx";
string ClientCertPassword = "<cert-password>";
// ...
X509Certificate2 certificate = new X509Certificate2(Path.GetFullPath(ClientCertFile),
    ClientCertPassword,
    X509KeyStorageFlags.Exportable);
Certificate cert = new Certificate(certificate);
browser.SelectCertificateHandler
    = new Handler<SelectCertificateParameters, SelectCertificateResponse>(p =>
    {
        return SelectCertificateResponse.Select(cert);
    });
Dim ClientCertFile = "<cert-file>.pfx"
Dim ClientCertPassword = "<cert-password>"
' ...
Dim certificate = New X509Certificate2(Path.GetFullPath(ClientCertFile),
                                       ClientCertPassword,
                                       X509KeyStorageFlags.Exportable)
Dim cert = New Certificate(certificate)
browser.SelectCertificateHandler =
    New Handler(Of SelectCertificateParameters, SelectCertificateResponse)(
        Function(p) SelectCertificateResponse.Select(cert))

打印

配置打印

class MyPrintHandler : PrintHandler
{
    public PrintStatus OnPrint(PrintJob printJob)
    {
        PrintSettings printSettings = printJob.PrintSettings;
        printSettings.PrinterName = "Microsoft XPS Document Writer";
        printSettings.Landscape = true;
        printSettings.PrintBackgrounds = true;
        return PrintStatus.CONTINUE;
    }
}
// ...
browser.PrintHandler = new MyPrintHandler();
Class MyPrintHandler
    Inherits PrintHandler

    Public Function OnPrint(ByVal printJob As PrintJob) As PrintStatus
        Dim printSettings As PrintSettings = printJob.PrintSettings
        printSettings.PrinterName = "Microsoft XPS Document Writer"
        printSettings.Landscape = True
        printSettings.PrintBackgrounds = True
        Return PrintStatus.CONTINUE
    End Function
End Class
' ...
browser.PrintHandler = New MyPrintHandler()

2.0

DotNetBrowser 2.0 版中删除了可配置打印的功能。现在会显示标准的打印预览对话框,您可以在其中提供所需的设置:

browser.PrintHandler =
    new Handler<PrintParameters, PrintResponse>(p =>
    {
        return PrintResponse.ShowPrintPreview();
    });
browser.PrintHandler =
    New Handler(Of PrintParameters, PrintResponse)(
        Function(p) PrintResponse.ShowPrintPreview())

抑制打印

1.x

class MyPrintHandler : PrintHandler
{
    public PrintStatus OnPrint(PrintJob printJob)
    {
        return PrintStatus.CANCEL;
    }
}
// ...
browser.PrintHandler = new MyPrintHandler();
Class MyPrintHandler
    Inherits PrintHandler

    Public Function OnPrint(ByVal printJob As PrintJob) As PrintStatus
        Return PrintStatus.CANCEL
    End Function
End Class
' ...
browser.PrintHandler = New MyPrintHandler()

2.0

browser.PrintHandler =
    new Handler<PrintParameters, PrintResponse>(p =>
    {
        return PrintResponse.Cancel();
    });
browser.PrintHandler =
    New Handler(Of PrintParameters, PrintResponse)(
        Function(p) PrintResponse.Cancel())

缓存

清除 HTTP 缓存

1.x

browser.CacheStorage.ClearCache(() => 
{
    // HTTP 磁盘缓存已被清除。
});
browser.CacheStorage.ClearCache(Sub()
    ' HTTP Disk Cache has been cleared.
End Sub)

2.0

await engine.HttpCache.ClearDiskCache();
// HTTP 磁盘缓存已被清除。

engine.HttpCache.ClearDiskCache().Wait();
// HTTP 磁盘缓存已被清除。

``vb Await engine.HttpCache.ClearDiskCache() ‘ HTTP 磁盘缓存已被清除。

或
```vb
engine.HttpCache.ClearDiskCache().Wait()
' HTTP 磁盘缓存已被清除。

Cookies

访问 cookies

1.x

List<Cookie> cookies = browser.CookieStorage.GetAllCookies();
Dim cookies As List(Of Cookie) = browser.CookieStorage.GetAllCookies()

2.0

IEnumerable<Cookie> cookies = await engine.CookieStore.GetAllCookies();
Dim cookies As IEnumerable(Of Cookie) = Await engine.CookieStore.GetAllCookies()

IEnumerable<Cookie> cookies = engine.CookieStore.GetAllCookies().Result;
Dim cookies As IEnumerable(Of Cookie) = engine.CookieStore.GetAllCookies().Result

渲染进程终止

每个浏览器实例都运行在单独的本地进程中,网页就是在该进程中渲染的。

有时由于插件崩溃,该进程会意外退出。渲染进程终止事件可用于接收有关意外渲染进程终止的通知。

1.x

browser.RenderGoneEvent += (s, e) =>
{
    TerminationStatus status = e.TerminationStatus;
};
AddHandler browser.RenderGoneEvent , Sub(s, e)
    Dim status As TerminationStatus = e.TerminationStatus
End Sub

2.0

browser.RenderProcessTerminated += (s, e) =>
{
    TerminationStatus status = e.TerminationStatus;
};
AddHandler browser.RenderProcessTerminated , Sub(s, e)
    Dim status As TerminationStatus = e.TerminationStatus
End Sub

Chromium

开关

该库不支持所有可能的 Chromium 开关。它允许使用开关配置 Chromium,但我们不保证传递的开关能够正常工作或完全工作。我们建议在使用前检查该功能。

1.x

BrowserPreferences.SetChromiumSwitches(
    "--<switch_name>",
    "--<switch_name>=<switch_value>"
);
BrowserPreferences.SetChromiumSwitches(
    "--<switch_name>", 
    "--<switch_name>=<switch_value>"
)

2.0

IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
    ChromiumSwitches = { "--<switch-name>", "--<switch-name>=<switch-value>" }
}.Build());
Dim engineOptions = New EngineOptions.Builder
engineOptions.ChromiumSwitches.Add("--<switch-name>")
engineOptions.ChromiumSwitches.Add("--<switch-name>=<switch-value>")

Dim engine = EngineFactory.Create(engineOptions.Build())

API 密钥

1.x

BrowserPreferences.SetChromiumVariable(
        "GOOGLE_API_KEY", "My API Key");
BrowserPreferences.SetChromiumVariable(
        "GOOGLE_DEFAULT_CLIENT_ID", "My Client ID");
BrowserPreferences.SetChromiumVariable(
        "GOOGLE_DEFAULT_CLIENT_SECRET", "My Client Secret");
BrowserPreferences.SetChromiumVariable( _
    "GOOGLE_API_KEY", "My API Key")
BrowserPreferences.SetChromiumVariable( _
    "GOOGLE_DEFAULT_CLIENT_ID", "My Client ID")
BrowserPreferences.SetChromiumVariable( _
    "GOOGLE_DEFAULT_CLIENT_SECRET", "My Client Secret")

2.0

IEngine engine = EngineFactory.Create(new EngineOptions.Builder
{
    GoogleApiKey = "<api-key>",
    GoogleDefaultClientId = "<client-id>",
    GoogleDefaultClientSecret = "<client-secret>"
}.Build());
Dim engine As IEngine = EngineFactory.Create(New EngineOptions.Builder With {
    .GoogleApiKey = "<api-key>",
    .GoogleDefaultClientId = "<client-id>",
    .GoogleDefaultClientSecret = "<client-secret>"
}.Build())

日志记录

在新版本中,我们改进了日志 API。有关如何配置日志记录的更多信息,请阅读故障排除指南。

常见问题

DotNetBrowser 1.x 版本将支持多久?

DotNetBrowser 1.x 版本将支持到 2021 年 2 月。所有新功能、Chromium 升级、对新操作系统和 .NET 实现的支持、不同的增强功能,都将在最新(主流)版本的基础上应用。

我可以免费升级到 DotNetBrowser 2 吗?

如果您已拥有 DotNetBrowser 1 的商业许可证,并已激活订阅,那么您可以免费获得 DotNetBrowser 2 的商业许可证密钥。如对此有任何疑问,请联系我们的销售团队

我有一个指南中未涉及的案例。我该怎么办?

建议查看我们的指南部分。DotNetBrowser 1.0 版本和 2.0 版本的功能几乎完全相同。因此,如果此迁移指南未描述您使用的 DotNetBrowser 版本 1.0 功能的替代方案,您可以在我们的指南中找到类似功能的描述,其中的文档按功能区域分组。

如果您没有在指南中看到所需功能的描述,请提交工单

Go Top