using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
public static class Program
{
[STAThread]
public static void Main()
{
using (var browser = new WebBrowser())
{
browser.Navigate(string.Empty);
browser.Document.InvokeScript("execScript", new object[] { "function set_obj(obj) { window.obj = obj }" });
browser.Document.InvokeScript("execScript", new object[] { "function say_hello() { window.obj.WriteLine('Hello world') }" });
browser.Document.InvokeScript("set_obj", new object[] { new Obj() });
browser.Document.InvokeScript("say_hello");
开发者_运维技巧 browser.Document.InvokeScript("setTimeout", new object[] { "say_hello()", 100 });
Console.ReadKey();
}
}
}
[ComVisible(true)]
public sealed class Obj
{
public void WriteLine(string message)
{
Console.WriteLine(message);
}
}
An immediate invocation of the method say_hello works fine, but when I postpone it using setTimeout, it is not invoked. Why? Is there any workaround?
As user @controlflow pointed, I need a message loop in my application to make setTimeout work. Adding the following line helps:
Application.Run(new Form { Controls = { browser }, WindowState = FormWindowState.Minimized, ShowInTaskbar = false });
Don't put the parentheses after say_hello, because you're not trying to call it there, but pass it as a delegate to a function. So try:
browser.Document.InvokeScript("setTimeout", new object[] { "say_hello", 100 });
Also, are there any errors in the console?
Update:
Try:
browser.Document.InvokeScript("setTimeout(say_hello, 100);");
Also try:
browser.Document.InvokeScript("setTimeout", new object[] { "say_hello", "100" });
Whatever the issue is, there's probably a JavaScript error being swallowed somewhere. Try to write out the rendered markup and script and run it in a normal web page in browser.
You should change the following line
browser.Document.InvokeScript("say_hello");
to
browser.Document.InvokeScript("say_hello()");
It throws a javascript exception, and probably it's the reason for the next command not to execute.
精彩评论