3
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?

Vladimir Reshetnikov
  • 11,750
  • 4
  • 30
  • 51
  • I also tried to pass a function instead of string as an argument to setTimeout - it didn't help: browser.Document.InvokeScript("setTimeout", new object[] { ((dynamic) browser.Document.Window.DomWindow).say_hello, 100 }); – Vladimir Reshetnikov Jul 05 '11 at 18:53

3 Answers3

4

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 });
Vladimir Reshetnikov
  • 11,750
  • 4
  • 30
  • 51
2

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.

Kon
  • 27,113
  • 11
  • 60
  • 86
0

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.

Yiğit Yener
  • 5,796
  • 1
  • 23
  • 26
  • parands should not be included. see documentatio: http://msdn.microsoft.com/en-us/library/4b1a88bz.aspx – Kon Jul 05 '11 at 19:13