Browser
本指南将介绍如何创建、使用和关闭 Browser
。
有关 DotNetBrowser 架构、其主要组件及其交互的更多信息,请参阅架构指南。
创建浏览器
要创建一个新的 IBrowser
示例,使用 IProfile.CreateBrowser()
方法。 例如:
IBrowser browser = engine.Profiles.Default.CreateBrowser();
Dim browser As IBrowser = engine.Profiles.Default.CreateBrowser()
如果您使用 IEngine.CreateBrowser()
方法,那么浏览器将会在默认配置文件下创建。 然而,这种方法已经过时了,建议改用相应的配置文件实例来代替。
此方法执行以下操作:
- 创建一个新的
IBrowser
示例。 - 在其中加载
about:blank
网页并等待网页完全加载。
处理浏览器
IBrowser
实例在 Chromium Main 进程中运行,并分配要释放的内存和系统资源。 当不再需要 IBrowser
实例时,使用 IBrowser.Dispose()
方法处理它。 因此,所有分配的内存和系统资源都将被释放。 请参阅以下代码示例:
IBrowser browser = engine.Profiles.Default.CreateBrowser();
// ...
browser.Dispose();
Dim browser As IBrowser = engine.Profiles.Default.CreateBrowser()
' ...
browser.Dispose()
尝试使用已处理的 IBrowser
实例会导致 ObjectDisposedException
。
在下列情况下,IBrowser
实例将自动释放:
- 当其父
IEngine
实例被意外处理或崩溃时。 - 当此
IBrowser
实例是一个 弹出窗口,并使用window.close()
从 JavaScript 关闭时。
使用 Disposed
事件可在 IBrowser
实例被处理时收到通知。 请参阅以下代码示例:
browser.Disposed += (sender, event => {});
AddHandler browser.Disposed, Sub(s,e)
End Sub
使用 IsDisposed
属性检查 IBrowser
是否已被处理:
bool disposed = browser.IsDisposed;
Dim disposed As Boolean = browser.IsDisposed
浏览器大小
默认情况下,IBrowser
大小为空。 如果要在网页上使用 DOM 或 查找文本,请先设置浏览器大小。
要更新 IBrowser
的大小,请使用其 Size
属性。 请参阅以下代码示例:
browser.Size = new Size(800, 600);
browser.Size = New Size(800, 600)
此方法通知 Chromium IBrowser
实例的大小已更改。 Chromium 将异步更新加载的网页的 DOM 布局并重新绘制其内容。 设置该属性后,可能需要一些时间才能重新绘制网页。
浏览器设置
可以通过 IBrowser.Settings
属性自定义浏览器设置。 浏览器设置可用于禁用浏览器中的图像、插件或 JavaScript、隐藏滚动条、禁用应用程序缓存。 请参阅以下代码示例:
// 禁用所有脚本。
browser.Settings.JavaScriptEnabled = false;
' 禁用所有脚本。
browser.Settings.JavaScriptEnabled = False
指定 WebRTC IP 处理策略
DotNetBrowser 允许自定义 WebRTC IP 处理策略。 这些是 DotNetBrowser 中可用的 WebRTC 策略:
-
Default
- Chromium 的默认行为。 设置此策略后,WebRTC 可以枚举所有接口并将它们绑定以发现公共接口。 -
DefaultPublicInterfacesOnly
- 告知浏览器使用默认的公共网络适配器发送 WebRTC 流量。 这将是系统-VPN 用户的 VPN 适配器。 WebRTC 必须只使用 http 使用的默认路由。 -
DefaultPublicAndPrivateInterfaces
- 与DefaultPublicInterfacesOnly
相同,但它还允许 WebRTC 流量通过默认专用接口传输到本地网络。 -
DisableNonProxiedUdp
- 禁用非代理 UDP 并强制代理。 此策略强制使用代理,并且仅允许通过 UDP 代理传输 WebRTC 流量。 根据 UDP 代理的使用情况,它能有效地禁用大多数用户的 WebRTC 通信。
以下示例代码演示了如何为浏览器实例配置 WebRTC IP 处理策略:
browser.Settings.WebRtcIpHandlingPolicy =
WebRtcIpHandlingPolicy.DisableNonProxiedUdp;
browser.Settings.WebRtcIpHandlingPolicy =
WebRtcIpHandlingPolicy.DisableNonProxiedUdp
深色模式
您可以在网页上强制使用首选配色方案,如下所示:
// 强制启用深色模式。
browser.Settings.PreferredColorScheme = PreferredColorScheme.Dark;
// 强制启用浅色模式。
browser.Settings.PreferredColorScheme = PreferredColorScheme.Light;
' 强制启用深色模式。
browser.Settings.PreferredColorScheme = PreferredColorScheme.Dark;
// 强制启用浅色模式。
browser.Settings.PreferredColorScheme = PreferredColorScheme.Light
上述设置仅适用于尊重 prefers-color-scheme
媒体查询的网站。
用户代理
您可以覆盖默认的用户代理字符串,并将 IBrowser
配置为使用自定义字符串。 请参阅以下代码示例:
browser.UserAgent = "<user-agent>";
browser.UserAgent = "<user-agent>"
相同的属性可用于获取当前用户代理字符串:
string userAgent = browser.UserAgent;
Dim userAgent As String = browser.UserAgent
远程调试 URL
要获取在特定 IBrowser
实例中加载的网页的远程调试 URL,请使用以下方法:
string url = browser.DevTools.RemoteDebuggingUrl;
Dim url As String = browser.DevTools.RemoteDebuggingUrl
仅当 IEngine
配置有远程调试端口时,此方法才会返回有效的 URL。 否则,属性值为空。
DevTools
要在不配置远程调试端口的情况下以编程方式显示 DevTools 窗口,请使用以下代码:
browser.DevTools.Show();
browser.DevTools.Show()
查看页面源代码
您可以使用以下方法查看已加载网页或框架的源代码:
browser.MainFrame?.ViewSource();
browser.MainFrame?.ViewSource()
上面的代码告诉 Chromium 使用主框架的 HTML 源代码创建并打开一个弹出窗口。
鼠标和键盘事件
DotNetBrowser 允许使用以下处理程序在鼠标和键盘事件发送到网页之前拦截它们:
IBrowser.Mouse.Entered.Handler
IBrowser.Mouse.Exited.Handler
IBrowser.Mouse.Pressed.Handler
IBrowser.Mouse.Released.Handler
IBrowser.Mouse.Moved.Handler
IBrowser.Mouse.WheelMoved.Handler
IBrowser.Keyboard.KeyPressed.Handler
IBrowser.Keyboard.KeyTyped.Handler
IBrowser.Keyboard.KeyReleased.Handler
以下代码示例演示了如何抑制鼠标滚轮事件:
browser.Mouse.WheelMoved.Handler =
new Handler<IMouseWheelMovedEventArgs, InputEventResponse>(e =>
{
return InputEventResponse.Suppress;
});
browser.Mouse.WheelMoved.Handler =
New Handler(Of IMouseWheelMovedEventArgs, InputEventResponse)(Function(e)
Return InputEventResponse.Suppress
End Function)
您可以使用这些处理程序获取有关鼠标和键盘事件的通知,从而在应用程序中实现热键。 您还可以抑制默认快捷方式,如 Ctrl+C
。 请参阅以下代码示例:
browser.Keyboard.KeyPressed.Handler =
new Handler<IKeyPressedEventArgs, InputEventResponse>(e =>
{
bool keyCodeC = e.VirtualKey == KeyCode.VkC;
bool controlDown = e.Modifiers.ControlDown;
if (controlDown && keyCodeC)
{
return InputEventResponse.Suppress;
}
return InputEventResponse.Proceed;
});
browser.Keyboard.KeyPressed.Handler =
New Handler(Of IKeyPressedEventArgs, InputEventResponse)(Function(e)
Dim keyCodeC As Boolean = e.VirtualKey = KeyCode.VkC
Dim controlDown As Boolean = e.Modifiers.ControlDown
If controlDown AndAlso keyCodeC Then
Return InputEventResponse.Suppress
End If
Return InputEventResponse.Proceed
End Function)
模拟用户输入
DotNetBrowser 允许模拟鼠标和键盘输入。 模拟在 WPF 和 Windows 窗体的离屏和硬件加速渲染模式下都可用。
您可以通过引发鼠标和键盘事件来模拟输入。 例如,下面是模拟打字的方法:
private static void SimulateKey(IKeyboard keyboard, KeyCode key, string keyChar,
KeyModifiers modifiers = null)
{
modifiers = modifiers ?? new KeyModifiers();
KeyPressedEventArgs keyDownEventArgs = new KeyPressedEventArgs
{
KeyChar = keyChar,
VirtualKey = key,
Modifiers = modifiers
};
KeyTypedEventArgs keyPressEventArgs = new KeyTypedEventArgs
{
KeyChar = keyChar,
VirtualKey = key,
Modifiers = modifiers
};
KeyReleasedEventArgs keyUpEventArgs = new KeyReleasedEventArgs
{
VirtualKey = key,
Modifiers = modifiers
};
keyboard.KeyPressed.Raise(keyDownEventArgs);
keyboard.KeyTyped.Raise(keyPressEventArgs);
keyboard.KeyReleased.Raise(keyUpEventArgs);
}
Private Shared Sub SimulateKey(keyboard As IKeyboard, key As KeyCode, keyChar As String,
Optional modifiers As KeyModifiers = Nothing)
modifiers = If(modifiers, New KeyModifiers())
Dim keyPressedEventArgs = New KeyPressedEventArgs With {
.KeyChar = keyChar,
.VirtualKey = key,
.Modifiers = modifiers
}
Dim keyTypedEventArgs = New KeyTypedEventArgs With {
.KeyChar = keyChar,
.VirtualKey = key,
.Modifiers = modifiers
}
Dim keyReleasedEventArgs = New KeyReleasedEventArgs With {
.VirtualKey = key,
.Modifiers = modifiers
}
keyboard.KeyPressed.Raise(keyPressedEventArgs)
keyboard.KeyTyped.Raise(keyTypedEventArgs)
keyboard.KeyReleased.Raise(keyReleasedEventArgs)
End Sub
IKeyboard keyboard = browser.Keyboard;
SimulateKey(keyboard, KeyCode.VkH, "H");
SimulateKey(keyboard, KeyCode.VkE, "e");
SimulateKey(keyboard, KeyCode.VkL, "l");
SimulateKey(keyboard, KeyCode.VkL, "l");
SimulateKey(keyboard, KeyCode.VkO, "o");
SimulateKey(keyboard, KeyCode.Space, " ");
// 模拟一些非字母字符的输入。
SimulateKey(keyboard, KeyCode.Vk5, "%", new KeyModifiers {ShiftDown = true});
SimulateKey(keyboard, KeyCode.Vk2, "@", new KeyModifiers {ShiftDown = true});
Dim keyboard As IKeyboard = browser.Keyboard
SimulateKey(keyboard, KeyCode.VkH, "H")
SimulateKey(keyboard, KeyCode.VkE, "e")
SimulateKey(keyboard, KeyCode.VkL, "l")
SimulateKey(keyboard, KeyCode.VkL, "l")
SimulateKey(keyboard, KeyCode.VkO, "o")
SimulateKey(keyboard, KeyCode.Space, " ")
' 模拟一些非字母字符的输入。
SimulateKey(keyboard, KeyCode.Vk5, "%",
New KeyModifiers() With {.ShiftDown = True})
SimulateKey(keyboard, KeyCode.Vk2, "@",
New KeyModifiers() With {.ShiftDown = True})
我们的存储库中提供了完整的示例:
WinForms (C#,
VB.NET)
WPF (C#,
VB.NET)
您可以通过依次引发 IMouse.Moved
、 IMouse.Pressed
和 IMouse.Released
事件来模拟鼠标单击。 例如,下面是模拟单击的方法:
IMouse mouse = browser.Mouse;
MouseButton mouseButton = MouseButton.Left;
Point location = new Point(10, 10);
MouseMovedEventArgs moveEvent = new MouseMovedEventArgs
{
Location = location
};
MousePressedEventArgs pressEvent = new MousePressedEventArgs
{
Location = location,
Button = mouseButton,
ClickCount = 1
};
MouseReleasedEventArgs releaseEvent = new MouseReleasedEventArgs
{
Button = mouseButton,
ClickCount = 1,
Location = location
};
mouse.Moved.Raise(moveEvent);
Thread.Sleep(200);
mouse.Pressed.Raise(pressEvent);
Thread.Sleep(200);
mouse.Released.Raise(releaseEvent);
Dim mouse As IMouse = browser.Mouse
Dim mouseButton As MouseButton = MouseButton.Left
Dim location As New Point(10, 10)
Dim moveEvent As New MouseMovedEventArgs With {.Location = location}
Dim pressEvent As New MousePressedEventArgs With {
.Location = location,
.Button = mouseButton,
.ClickCount = 1
}
Dim releaseEvent As New MouseReleasedEventArgs With {
.Button = mouseButton,
.ClickCount = 1,
.Location = location
}
mouse.Moved.Raise(moveEvent)
Thread.Sleep(200)
mouse.Pressed.Raise(pressEvent)
Thread.Sleep(200)
mouse.Released.Raise(releaseEvent)
WebRTC 屏幕共享
Chromium 提供了允许共享整个屏幕、应用程序窗口或网页的内置功能。 默认情况下,DotNetBrowser 会显示一个标准对话框,供用户选择捕获源:
如果不想显示此对话框,可以通过编程方式处理请求和选择捕获源。 例如:
browser.Capture.StartSessionHandler =
new Handler<StartSessionParameters, StartSessionResponse>(p =>
{
// 告诉浏览器实例启动新的捕获会话,并指定
// 捕获源。
return StartSessionResponse.SelectSource(p.Sources.Screens.FirstOrDefault(),
AudioMode.Ignore);
});
browser.Capture.StartSessionHandler =
New Handler(Of StartSessionParameters, StartSessionResponse)(Function(p)
' 告诉浏览器实例启动新的捕获会话,并指定
' 捕获源。
Return StartSessionResponse.SelectSource(p.Sources.Screens.FirstOrDefault(),
AudioMode.Ignore)
End Function)
要以编程方式停止会话,请使用以下方法:
// 获取当前浏览器的所有捕获会话。
IReadOnlyList<ISession> sessions = browser.Capture.Sessions;
foreach (ISession session in sessions)
{
string sourceName = session.Source.Name;
bool isActive = session.IsActive;
// 停止会话。
session.Stop();
}
' 获取当前浏览器的所有捕获会话。
Dim sessions As IReadOnlyList(Of ISession) = browser.Capture.Sessions
For Each session As ISession In sessions
Dim sourceName As String = session.Source.Name
Dim isActive As Boolean = session.IsActive
' 停止会话。
session.Stop()
Next
您还可以禁止显示屏幕共享请求和标准对话框。 这是示例:
browser.Capture.StartSessionHandler =
new Handler<StartSessionParameters, StartSessionResponse>(p =>
{
// 取消共享操作。
return StartSessionResponse.Cancel();
});
browser.Capture.StartSessionHandler =
New Handler(Of StartSessionParameters, StartSessionResponse)(Function(p)
' 取消共享操作。
Return StartSessionResponse.Cancel()
End Function)
拖放
自 DotNetBrowser 2.3 起,可以在硬件加速渲染模式下拦截网页上的拖入和拖出事件。 为此,您需要使用 EnterDragHandler
和 DropHandler
。 例如:
browser.DragAndDrop.EnterDragHandler =
new Handler<EnterDragParameters>(OnDragEnter);
browser.DragAndDrop.DropHandler = new Handler<DropParameters>(OnDrop);
browser.DragAndDrop.EnterDragHandler =
New Handler(Of EnterDragParameters)(AddressOf OnDragEnter)
browser.DragAndDrop.DropHandler = New Handler(Of DropParameters)(AddressOf OnDrop)
private void OnDragEnter(EnterDragParameters arg)
{
if (arg.Event.DropData != null)
{
//将文件名写入调试输出。
foreach (IFileValue file in arg.Event.DropData.Files)
{
Debug.WriteLine($"OnDragEnter: File = {file?.FileName}");
}
}
}
private void OnDrop(DropParameters arg)
{
if (arg.Event.DropData != null)
{
//将文件名写入调试输出。
foreach (IFileValue file in arg.Event.DropData.Files)
{
Debug.WriteLine($"OnDrop: File = {file?.FileName}");
}
}
}
Private Sub OnDragEnter(arg As EnterDragParameters)
If arg.Event.DropData IsNot Nothing Then
' 将文件名写入调试输出。
For Each file As IFileValue In arg.Event.DropData.Files
Debug.WriteLine($"OnDragEnter: File = {file?.FileName}")
Next file
End If
End Sub
Private Sub OnDrop(arg As DropParameters)
If arg.Event.DropData IsNot Nothing Then
' 将文件名写入调试输出。
For Each file As IFileValue In arg.Event.DropData.Files
Debug.WriteLine($"OnDrop: File = {file?.FileName}")
Next file
End If
End Sub
在 .NET Framework 中,还可以在这些处理程序的作用范围内使用 IDataObject
实例来接收和处理拖放数据的 Windows 特定表示形式。 如果指定了 --enable-com-in-drag-drop
Chromium switch,该功能就会可用。 例如:
private void OnDragEnter(EnterDragParameters arg)
{
LogData(arg.Event.DropData, nameof(OnDragEnter));
Debug.WriteLine($"Data is null? {(arg.Event.DataObject == null)}");
System.Runtime.InteropServices.ComTypes.IDataObject dataObject =
arg.Event.DataObject;
if (dataObject != null)
{
// 处理 IDataObject 中的数据
ExtractData(nameof(OnDragEnter), new DataObject(dataObject));
}
}
private void OnDrop(DropParameters arg)
{
LogData(arg.Event.DropData, nameof(OnDrop));
Debug.WriteLine($"Data is null? {(arg.Event.DataObject == null)}");
System.Runtime.InteropServices.ComTypes.IDataObject dataObject =
arg.Event.DataObject;
if (dataObject != null)
{
// 处理 IDataObject 中的数据
ExtractData(nameof(OnDrop), new DataObject(dataObject));
}
}
Private Sub OnDragEnter(arg As EnterDragParameters)
LogData(arg.Event.DropData, NameOf(OnDragEnter))
Debug.WriteLine($"Data is null? {(arg.Event.DataObject Is Nothing)}")
Dim dataObject As IDataObject = arg.Event.DataObject
If dataObject IsNot Nothing Then
' 处理 IDataObject中的数据。
ExtractData(NameOf(OnDragEnter), New DataObject(dataObject))
End If
End Sub
Private Sub OnDrop(arg As DropParameters)
LogData(arg.Event.DropData, NameOf(OnDrop))
Debug.WriteLine($"Data is null? {(arg.Event.DataObject Is Nothing)}")
Dim dataObject As IDataObject = arg.Event.DataObject
If dataObject IsNot Nothing Then
' 处理 IDataObject 中的数据。
ExtractData(NameOf(OnDrop), New DataObject(dataObject))
End If
End Sub
如需完整示例,请导航至我们的存储库: C#, VB.NET.
在离屏渲染模式下,不支持拖放操作,并且已完全禁用。
标题事件
TitleChanged
事件表示主框架中文档的标题已更改。
要在文档标题更改时获得通知,请使用 TitleChanged
监听器,如下面的代码示例所示:
browser.TitleChanged += delegate (object sender, TitleChangedEventArgs e)
{
string mainDocumentTitle = e.Title;
};
AddHandler browser.TitleChanged, Sub(sender As Object, e As TitleChangedEventArgs)
Dim mainDocumentTitle As String = e.Title
End Sub
状态事件
当用户将光标移到链接上时,Chromium 引擎会在状态栏中显示其 URL。 JavaScript 代码也可以使用 window.statusproperty
以编程方式更改状态栏中的文本。 DotNetBrowser API 提供了获取状态栏文本更改通知的功能。
StatusChanged
事件表示状态栏文本已更改。
下面的代码示例演示了如何使用此功能:
browser.StatusChanged += delegate(object sender, StatusChangedEventArgs e)
{
string statusText = e.Text;
};
AddHandler browser.StatusChanged, Sub(sender As Object, e As StatusChangedEventArgs)
Dim statusText As String = e.Text
End Sub
渲染进程终止事件
每个 IBrowser
实例都与渲染网页的独立本地进程绑定。 默认情况下,Chromium 会为用户访问的每个网站实例创建一个渲染进程。 这样可以确保不同网站的页面是独立渲染的,同一网站的不同访问也能相互隔离。 因此,站点实例中的故障(例如,渲染器崩溃)或大量资源使用不会影响浏览器的其余部分。
有时这个进程会意外终止。 要接收有关渲染进程终止的通知,您可以订阅 IBrowser.RenderProcessTerminated
事件。 RenderProcessTerminatedEventArgs.ExitCode
值可用于确定这是预期的进程终止还是失败。
当您收到有关渲染进程意外终止的通知时,您可以像 Google Chrome 一样显示一个”sad”图标,例如,通知用户此特定实例崩溃。
如果在崩溃后刷新或加载相同或其他 URL,则会恢复渲染过程和 IBrowser
实例:
browser.RenderProcessTerminated += (sender, e) =>
{
int exitCode = e.ExitCode;
if (exitCode != 0)
{
// 渲染进程意外终止。
}
};
AddHandler browser.RenderProcessTerminated, Sub(sender, e)
Dim exitCode As Integer = e.ExitCode
If exitCode <> 0 Then
' 渲染进程意外终止。
End If
End Sub