Introdução
Instalação
Guias
- Engine
- Perfil
- Navegador
- BrowserView
- Navegação
- Conteúdo
- Menu de contexto
- DOM
- JavaScript
- Pop-ups
- Diálogos
- Downloads
- Rede
- Cache
- Cookies
- Proxy
- Autenticação
- Permissões
- Plugins
- Impressão
- Senhas
- Perfis de dados do usuário
- Cartões de crédito
- Mídia
- Zoom
- Corretor ortográfico
- Implantação
- Chromium
Resolução de problemas
- Registro
- Exceções comuns
- A aplicação não termina
- O vídeo não é reproduzido
- Não é possível iniciar sessão na conta Google
- Os dados do usuário não são armazenados
- Esquema de cores
- Falha no início
- Início lento no Windows
- Aplicação .NET que não responde
- Encerramento inesperado do processo Chromium
- Comportamento inesperado
- Fim do suporte do Windows 7/8/8.1
Migração
JavaScript
Este guia descreve como acessar o JavaScript na página Web carregada, executar código JavaScript, injetar objetos .NET para chamar o .NET a partir do JavaScript e outras funcionalidades.
Executando JavaScript
O DotNetBrowser permite acessar e executar código JavaScript na página Web carregada.
Para acessar o JavaScript, certifique-se de que a página Web está completamente carregada e que o JavaScript está ativo.
Para executar código JavaScript, utilize o método IFrame.ExecuteJavaScript(string)
. Este método devolve uma Task
que pode ser utilizada para obter o resultado da execução. Obter a propriedade Task.Result
ou chamar o método Task.Wait()
bloqueia a execução da thread atual até que a execução do JavaScript esteja concluída.
Por predefinição, o método devolve uma Task<object>
que representa o resultado da execução. O resultado é null
se o JavaScript devolver null
ou undefined
. A sobrecarga genérica deste método efetua uma conversão direta e lança uma ClassCastException
se houver uma incompatibilidade de tipos. Se você precisar evitar isto, utilize a sobrecarga não genérica em combinação com o cast seguro, nomeadamente o operador as
.
O exemplo abaixo executa o código JavaScript que devolve um título do documento
:
string title = frame.ExecuteJavaScript<string>("document.title").Result;
Dim title As String = frame.ExecuteJavaScript(Of String)("document.title").Result
Você pode executar qualquer código JavaScript:
double number = frame.ExecuteJavaScript<double>("123").Result;
bool boolean = frame.ExecuteJavaScript<bool>("true").Result;
string str = frame.ExecuteJavaScript<string>("'Olá'").Result;
IJsObject window = frame.ExecuteJavaScript<IJsObject>("window").Result;
IElement body = frame.ExecuteJavaScript<IElement>("document.body").Result;
Dim number As Double = frame.ExecuteJavaScript(Of Double)("123").Result
Dim [boolean] As Boolean = frame.ExecuteJavaScript(Of Boolean)("true").Result
Dim str As String = frame.ExecuteJavaScript(Of String)("'Hello'").Result
Dim window As IJsObject = frame.ExecuteJavaScript(Of IJsObject)("window").Result
Dim body As IElement = frame.ExecuteJavaScript(Of IElement)("document.body").Result
Injetando JavaScript
É possível injetar um código JavaScript personalizado na página Web utilizando a propriedade IBrowser.InjectJsHandler
. Este manipulador destina-se a ser injetado:
- um objeto .NET no código JavaScript;
- um código JavaScript personalizado para execução posterior antes de quaisquer scripts serem executados no frame específico.
Veja o exemplo de código abaixo:
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)
A classe MyObject
pode ter o seguinte aspecto:
public class MyObject
{
public string SayHelloTo(string firstName) => "Hello " + firstName + "!";
}
Public Class MyObject
Public Function SayHelloTo(ByVal firstName As String) As String
Return "Hello " & firstName & "!"
End Function
End Class
Quando a propriedade é definida, é possível chamar métodos do objeto .NET injetado a partir do JavaScript:
window.myObject.SayHelloTo('John');
Este manipulador pode ser invocado várias vezes para a mesma moldura.
Evite executar um código JavaScript que modifique a árvore DOM da página Web que está sendo carregada. Não se deve utilizar a API DOM do DotNetBrowser para remover o frame para a qual este handler é invocado, caso contrário o processo de renderização é bloqueado.
Conversão de tipo
O JavaScript e o .NET funcionam com tipos primitivos diferentes. O DotNetBrowser implementa uma conversão automática de tipos de JavaScript para tipos .NET e vice-versa.
JavaScript para .NET
As seguintes regras são utilizadas para converter JavaScript em tipos .NET:
- Os números JavaScript são convertidos para
System.Double
- JavaScript
string
- paraSystem.String
- JavaScript
boolean
- paraSystem.Boolean
- JavaScript
null
eundefined
- paranull
- Os objetos JavaScript são envolvidos como
IJsObject
- Os objetos JavaScript DOM Node são agrupados como
IJsObject
eIEventTarget
.
No exemplo de código acima, sabemos que o document.title
é uma cadeia de caracteres, pelo que utilizamos a sobrecarga do método genérico com o parâmetro de tipo string
.
.NET para JavaScript
As seguintes regras são utilizadas para converter tipos .NET em JavaScript:
System.Double
- é convertido para JavaScriptNumber
;System.String
- para JavaScriptstring
;System.Boolean
- para JavaScriptboolean
;- .NET
null
- para JavaScriptnull
; IJsObject
- para um objeto JavaScript adequado;IEventTarget
- para um objeto JavaScript DOM Node adequado;System.Object
será envolvido num objeto JavaScript.
DOM wrappers
De acordo com as regras da conversão automática de tipos, os objetos DOM do JavaScript são agrupados como IJsObject
e IEventTarget
. É possível trabalhar com os objetos DOM do JavaScript utilizando a API DOM do DotNetBrowser.
No exemplo de código abaixo, devolvemos o documento
que representa um objeto DOM JavaScript. Neste caso, o tipo de valor de retorno pode ser definido como IJsObject
ou IDocument
:
IDoc document = frame.ExecuteJavaScript<IDocument>("document").Result;
Dim document As IDocument = frame.ExecuteJavaScript(Of IDocument)("document").Result
IJsObject document = frame.ExecuteJavaScript<IJsObject>("document").Result;
Dim document As IJsObject = frame.ExecuteJavaScript(Of IJsObject)("document").Result
Trabalhando com JsObject
Para trabalhar com objetos JavaScript a partir do código .NET, utilize a interface IJsObject
. Esta interface permite trabalhar com as propriedades do objeto e chamar as suas funções.
Propriedades
Para obter nomes de propriedades de um objeto JavaScript, incluindo propriedades dos objetos protótipo, utilize a propriedade IJsObjectPropertyCollection.Names
:
IEnumerable<string> propertyNames = jsObject.Properties.Names;
Dim propertyNames As IEnumerable(Of String) = jsObject.Properties.Names
Para verificar se o objeto JavaScript tem uma propriedade especificada, utilize o método IJsObjectPropertyCollection.Contains(string)
:
bool has = jsObject.Properties.Contains("<property-name>");
Dim has As Boolean = jsObject.Properties.Contains("<property-name>")
Para obter um valor da propriedade do objeto JavaScript pelo seu nome, utilize Properties[string]
. Ver o exemplo de código abaixo:
IJsObject document = frame.ExecuteJavaScript<IJsObject>("document").Result;
object title = document.Properties["title"];
Dim document As IJsObject = frame.ExecuteJavaScript(Of IJsObject)("document").Result
Dim title As Object = document.Properties("title")
As Properties[string]
também podem ser utilizadas para definir as propriedades do objeto JavaScript. Por exemplo:
document.Properties["title"] = "Novo Título";
document.Properties("title") = "Novo Título"
O valor de retorno é System.Object
que pode ser definido para o tipo pretendido. Para mais informações, consulte a seção Conversão de tipos.
É possível remover uma propriedade utilizando a seguinte abordagem:
bool success = jsObject.Properties.Remove("<property-name>");
Dim success As Boolean = jsObject.Properties.Remove("<property-name>")
Funções
Para chamar uma função com o nome e os argumentos necessários, utilize o método Invoke(string methodName, object... args)
. O exemplo de código abaixo demonstra como chamar a função JavaScript document.getElementById()
:
IJsObject element = document.Invoke("getElementById", "demo");
Dim element As IJsObject = document.Invoke("getElementById", "demo")
…o que é equivalente ao seguinte código em JavaScript:
var element = document.getElementById("demo");
O método lança JsException
se ocorrer um erro durante a execução da função.
Tipo dinâmico
É possível efetuar chamadas para objetos JavaScript como se mostra abaixo:
dynamic document = Browser.MainFrame.ExecuteJavaScript("document").Result;
document.write("Olá mundo!");
Dim document As Object = Browser.MainFrame.ExecuteJavaScript("document").Result
document.write("Olá mundo!")
Eis um exemplo mais complexo que demonstra como trabalhar com XMLHttpRequest
e enviar um pedido AJAX utilizando o tipo dinâmico
:
ligação tardia:
dynamic xhr = browser.MainFrame.ExecuteJavaScript("new XMLHttpRequest()").Result;
var url = "https://jsonplaceholder.typicode.com/todos/1";
xhr.open("GET", url, true);
// Executar função em readystatechange.
xhr.onreadystatechange = (Ação<dynamic>)((o) =>
{
if (xhr.readyState == 4 && xhr.status == 200)
{
System.Console.WriteLine(xhr.responseText);
}
});
// Enviar o nosso pedido.
xhr.send();
// Espera na thread principal para ver a resposta impressa.
Thread.Sleep(10000);
Dim xhr As Object
xhr = browser.MainFrame.ExecuteJavaScript("new XMLHttpRequest()").Result
Dim url = "https://jsonplaceholder.typicode.com/todos/1"
xhr.open("GET", url, true)
' Executar função em readystatechange.
xhr.onreadystatechange = Sub (o As Object)
If xhr.readyState = 4 And xhr.status = 200
System.Console.WriteLine(xhr.responseText.ToString())
End If
End Sub
' Enviar o pedido.
xhr.send()
' Espera na thread principal para ver a resposta impressa.
Thread.Sleep(10000)
Trabalhar com funções JavaScript
Desde o DotNetBrowser 2.1, é possível trabalhar com as funções JavaScript diretamente a partir do código .NET e passar a referência a uma função do JavaScript para o .NET. Por exemplo:
IJsFunction alert = frame.ExecuteJavaScript<IJsFunction>("window.alert").Result;
alert?.Invoke(window, "Olá mundo!");
Dim alert As IJsFunction = frame.ExecuteJavaScript(Of IJsFunction)("window.alert").Result
alert?.Invoke(window, "Olá mundo!")
Trabalhando com promessas JavaScript
Desde o DotNetBrowser 2.7 você pode trabalhar diretamente com as promessas JavaScript sem necessidade de criar um wrapper sobre IJsObject
. Por exemplo:
IJsPromise promise = browser.MainFrame
.ExecuteJavaScript<IJsPromise>("Promise.resolve(\"test\")")
.Result;
// Invoca algum código .NET quando a promessa é cumprida ou rejeitada.
promise.Then(o => Console.WriteLine("Promessa cumprida"),
e => Console.WriteLine("Promessa rejeitada"));
Dim promise As IJsPromise =
browser1.MainFrame.ExecuteJavaScript(
Of IJsPromise)("Promise.resolve(""test"")").Result
' Invoca algum código .NET quando a promessa é cumprida ou rejeitada.
promise.Then(Sub(o) Console.WriteLine("Promessa cumprida"),
Sub(e) Console.WriteLine("Promessa rejeitada"))
Chamando o .NET a partir do JavaScript
Quando você passa um System.Object
como um valor de propriedade ou um argumento ao chamar a função JavaScript, o objeto .NET será automaticamente convertido/envolvido num objeto JavaScript. Isso permite injetar objetos .NET em JavaScript e invocar os seus métodos públicos a partir do código JavaScript.
As amostras de código abaixo demonstram como passar um objeto .NET como um valor de propriedade e chamar o seu método público a partir do JavaScript:
public class MyObject {
public string SayHelloTo(string firstName) {
return "Hello " + firstName + "!";
}
}
Public Class MyObject
Public Function SayHelloTo(ByVal firstName As String) As String
Return "Hello " & firstName & "!"
End Function
End Class
IJsObject window = frame.ExecuteJavaScript<IJsObject>("window").Result;
window.Properties["MyObject"] = new MyObject();
Dim window As IJsObject = frame.ExecuteJavaScript(Of IJsObject)("window").Result
window.Properties("MyObject") = New MyObject()
Depois disso, você pode referir-se ao objeto e chamar o seu método a partir do código JavaScript:
consola.log(window.MyObject.SayHelloTo("John"));
A saída do console é o seguinte:
Olá João!
Conversão de tipo
A ponte JavaScript-.NET fornece a funcionalidade de conversão automática de tipos quando chama um método público do objeto .NET injetado a partir do JavaScript.
A biblioteca converte automaticamente o Number
JavaScript para o tipo .NET necessário se for possível. Se detectarmos que o número fornecido não pode ser convertido, por exemplo, para um byte
.NET sem perda de dados, a biblioteca lança uma exceção e notifica o JavaScript de que não existe nenhum método .NET adequado. Se o valor fornecido puder ser convertido sem perda de dados, a biblioteca converte-o e invoca o método .NET adequado.
Por exemplo, se você injetar o seguinte objeto .NET no JavaScript:
public sealed class MyObject {
public int Method(int intValue) {
return intValue;
}
}
Public NotInheritable Class MyObject
Public Function Method(ByVal intValue As Integer) As Integer
Return intValue
End Function
End Class
Depois disso, você pode chamá-lo a partir do JavaScript e passar o JavaScript Number
valor que pode ser convertido para e Integer
sem perda de dados:
window.MyObject.method(123);
No entanto, se você passar um valor Double
que não possa ser convertido para um Integer
sem perda de dados, você vai obter o seguinte erro:
window.MyObject.method(3.14); // <- erro
Injetar delegates
A outra maneira de chamar o .NET a partir do JavaScript é injetando delegates.
A ponte JavaScript-.NET permite que você associe um delegate a uma propriedade JavaScript. Esse delegate será tratado como uma função que pode ser invocada no código JavaScript.
Por exemplo, você pode registrar uma função JavaScript associada ao delegate utilizando o seguinte código:
IJsObject window = frame.ExecuteJavaScript<IJsObject>("window").Result;
if (window != null) {
window.Properties["sayHello"] = (Func<string, string>) ((args) => "Hello, " + args[0]);
}
Dim window As IJsObject = frame.ExecuteJavaScript(Of IJsObject)("window").Result
If window IsNot Nothing Then
window.Properties("sayHello") = CType(Function(args) "Hello, " & args(0),
Func(Of String, String))
End If
Agora, você pode invocar esta função em JavaScript da seguinte forma:
window.sayHello('John');
As regras de conversão de tipos não se aplicam aos delegates. O JavaScript Number
é sempre interpretado como Double
neste caso.
Mensagens do console
O DotNetBrowser permite receber todas as mensagens de saída enviadas para a Consola utilizando a função JavaScript console.log()
. Você pode ouvir as mensagens com os seguintes níveis:
DEBUG
LOG
WARNING
ERROR
Para obter uma notificação sobre a receção de uma mensagem pelo Console, utilize o evento ConsoleMessageReceived
. Veja o exemplo de código abaixo:
browser.ConsoleMessageReceived += (s, e) => {
string consoleMessage = e.Message;
ConsoleMessageReceivedEventArgs.MessageLevel level = e.Level;
};
AddHandler browser.ConsoleMessageReceived, Sub(s, e)
Dim consoleMessage As String = e.Message
Dim level As ConsoleMessageReceivedEventArgs.MessageLevel = e.Level
End Sub
Trabalhando com JSON
O DotNetBrowser JS - .NET Bridge API permite converter uma string que representa JSON num objeto/objetos JavaScript. O exemplo de código abaixo demonstra como criar um objeto JavaScript a partir de um string JSON:
string jsonString = "[123, \"Olá\"]";
IJsObject jsObject = browser.MainFrame.ParseJsonString<IJsObject>(jsonString);
Dim jsonString As String = "[123, ""Olá""]"
Dim jsObject As IJsObject = browser.MainFrame.ParseJsonString(Of IJsObject)(jsonString)
Se você tentar analisar o valor da string que não representa um JSON válido, é lançada uma JsException
.
No exemplo de código acima, a cadeia de caracteres "[123, \"Olá\"]"
a string JSON é convertida num objeto JavaScript apropriado. Neste caso, será convertido numa array.
É possível converter IJsObject
numa string JSON utilizando o método de extensão ToJsonString()
. Ele devolve uma string equivalente ao método JavaScript JSON.stringify()
:
string jsonRepresentation = jsObject.ToJsonString();
Dim jsonRepresentation As String = jsObject.ToJsonString()