Выполнение JavaScript на C# с CefSharp WPF вызывает ошибку

всякий раз, когда я пытаюсь выполнить JavaScript через C# с помощью CefSharp (стабильный 57.0), я получаю ошибку. Я просто пытаюсь выполнить функцию alert, Чтобы убедиться, что она работает, а затем протестировать ее с помощью моей собственной функции. Однако, кажется, я получаю ошибки, пытаясь это сделать.

public partial class WebBrowserWindow : Window
{
    public WebBrowserWindow()
    {
        InitializeComponent();
        webBrowser.MenuHandler = new ContextMenuHandler();
        webBrowser.RequestHandler = new RequestHandler();
    }

    //Trying to execute this with either method gives me an error.
    public void ExecuteJavaScript()
    {
        //webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");

        //webBrowser.ExecuteScriptAsync("alert('test');");
    }
}

Я пробовал оба способа выполнения скрипта.

первый:

webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");

дает мне это ошибка:

enter image description here

второй:

webBrowser.ExecuteScriptAsync("alert('test');");

дает мне эту ошибку:

enter image description here

моя цель-создать функцию C#, которая может выполнять функцию JavaScript в моем браузере CefSharp.

Я пробовал много ссылок / ссылок, и не было так много переполнения стека. Я тоже читал FAQ для CefSharp и не смог найти простых примеров, которые позволяют мне выполняйте JavaScript по желанию через C#.

кроме того, я проверил события, в которых загружается фрейм (он заканчивает загрузку) и выгружается (он не выгружается), и если webbrowser равен null (что не так), и сообщение от:

webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");

по-прежнему вызывает первую ошибку.

Я тестировал GetMainFrame (). Он всегда возвращает null. ВСЕГДА. Не имеет значения, как долго я жду, или какие условия я проверяю для.

важно

Я забыл добавить одну важную информацию, у меня есть 2 сборки в моем проекте. Оба они компилируются в отдельные исполняемые файлы:

помощником.исполняемый Главный.exe

main.exe имеет окно "CallUI", которое при нажатии кнопки выполняет метод, который я создал" ExecuteJavaScript ()", который находится внутри моего окна"BrowserWindow". Окно CallUI объявляется и инициализируется в Помощник.исполняемый.

поэтому в основном я пытаюсь использовать отдельную программу для открытия окна, нажмите кнопку, которая вызывает метод и выполняет javascript. Поэтому я думаю, что, поскольку это разные процессы, он говорит мне, что браузер равен нулю. Однако, когда я делаю все это в основном.exe он работает нормально. Есть обходной путь, который позволяет мне использовать отдельный процесс для создания окна с помощником.exe и выполнить Javascript из Main.exe?

2 ответов


до моего внимания дошло, что я обращался с проблемой неправильно.

моя проблема, на самом деле, не существует, если это всего лишь один процесс, удерживающий весь код вместе. Однако проблема заключалась в том, что в моем проекте был исполняемый файл, который пытался связаться с другим. На самом деле у меня никогда не было возможности помочь.exe, чтобы поговорить с моим главным.exe соответствующим образом.

из этого я узнал, что процессы пытались поговорить друг с другом без какого-либо общего доступа к адресу. Они живут в разных адресных пространствах, поэтому всякий раз мой помощник.exe попытался выполнить ту часть javascript, которая принадлежала Main.exe, он пытался выполнить сценарий в неинициализированной версии браузера, который принадлежал к его собственному адресному пространству, а не main.исполняемый.

Итак, как я решил эту проблему? Я должен был включить важную часть, которая позволила помощнику.exe процесс, чтобы поговорить с основным.процесс exe. Как я googled, как процессы могут разговаривать друг с другом, я узнал о MemoryMappedFiles. Поэтому я решил реализовать простой пример в своей программе, который позволяет Helper.exe для отправки сообщений в Main.исполняемый.

вот пример. Этот файл я создал под названием "MemoryMappedHandler.cs"

public class MemoryMappedHandler
{
    MemoryMappedFile mmf = MemoryMappedFile.CreateOrOpen("mmf1", 512);
    MemoryMappedViewStream stream;
    MemoryMappedViewAccessor accessor;
    BinaryReader reader;
    public static Message message = new Message();

    public MemoryMappedHandler()
    {
        stream = mmf.CreateViewStream();
        accessor = mmf.CreateViewAccessor();
        reader = new BinaryReader(stream);

        new Thread(() =>
        {
            while (stream.CanRead)
            {
                Thread.Sleep(500);
                message.MyStringWithEvent = reader.ReadString();
                accessor.Write(0, 0);
                stream.Position = 0;
            }
        }).Start();

    }

    public static void PassMessage(string message)
    {
        try
        {
            using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("mmf1"))
            {
                using (MemoryMappedViewStream stream = mmf.CreateViewStream(0, 512))
                {
                    BinaryWriter writer = new BinaryWriter(stream);
                    writer.Write(message);
                }
            }
        }
        catch (FileNotFoundException)
        {
            MessageBox.Show("Cannot Send a Message. Please open Main.exe");
        }
    }
}

это скомпилировано в dll, которая является основной.exe и помощником.exe может использовать.

помощником.exe использует метод PassMessage () для отправки сообщения в сопоставленный с памятью файл с именем "mmf1". Главный.exe, который должен быть открыт в любое время, заботится о создании того файла, который может получать сообщения от помощника.исполняемый. Я отправляю это сообщение классу, который содержит это сообщение, и каждый раз, когда он его получает, он активирует событие.

вот как выглядит класс сообщений:

[Serializable]
public class Message
{
    public event EventHandler HasMessage;

    public string _myStringWithEvent;

    public string MyStringWithEvent
    {
        get { return _myStringWithEvent; }
        set
        {
            _myStringWithEvent = value;
            if (value != null && value != String.Empty)
            {
                if (HasMessage != null)
                    HasMessage(this, EventArgs.Empty);
            }
        }
    }
}

наконец, мне пришлось инициализировать сообщение в моем классе WebBrowserWindow следующим образом:

public partial class WebBrowserWindow : Window
{
    public WebBrowserWindow()
    {
        InitializeComponent();
        webBrowser.MenuHandler = new ContextMenuHandler();
        webBrowser.RequestHandler = new RequestHandler();
        MemoryMappedHandler.message.HasMessage += Message_HasMessage;
    }

    private void Message_HasMessage(object sender, EventArgs e)
    {
        ExecuteJavaScript(MemoryMappedHandler.message.MyStringWithEvent);
    }

    public void ExecuteJavaScript(string message)
    {
        //webBrowser.GetMainFrame().ExecuteJavaScriptAsync("alert('test')");

        //webBrowser.ExecuteScriptAsync("alert('test');");
    }
}

и теперь он позволяет мне выполнить javascript, который мне нужен, отправив сообщение из Помощник.exe к основному.исполняемый.


вы пробовали эту ссылку? Содержит фрагмент, который проверяет, инициализирован ли браузер первым.

cefsharp выполнить javascript

private void OnIsBrowserInitializedChanged(object sender, IsBrowserInitializedChangedEventArgs args)
{
    if(args.IsBrowserInitialized)
    {
        browser.ExecuteScriptAsync("alert('test');");
    }
}