繁体   English   中英

使用CefSharp WPF在C#上执行JavaScript会导致错误

[英]Executing JavaScript on C# with CefSharp WPF causes Error

每当我尝试使用CefSharp(Stable 57.0)通过C#执行JavaScript时,我都会收到错误消息。 我只是尝试执行警报功能,所以我可以确保它可以工作,然后用我自己的函数测试它。 但是,我似乎在尝试这样做时遇到错误。

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')");

给我这个错误:

在此输入图像描述

第二:

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

给我这个错误:

在此输入图像描述

我的目标是创建一个可以在我的CefSharp浏览器中执行JavaScript函数的C#函数。

我尝试了很多链接/引用,堆栈溢出并没有那么多。 我还阅读了CefSharp的FAQ,找不到任何允许我通过C# 随意执行JavaScript的简单示例。

另外,我已经验证了加载Frame的事件(它完成加载)和卸载(它没有卸载),如果webbrowser为null(它不是),以及来自:的消息:

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

仍会导致第一个错误发生。

我测试了GetMainFrame()。 它总是返回null。 总是。 无论我等待多久,或者我检查的条件。

重要

我忘记添加一条关键信息,我的项目中有2个程序集。 它们都编译成单独的可执行文件:

Helper.exe Main.exe

main.exe有一个窗口“CallUI”,当单击一个按钮时,它会执行我创建的“ExecuteJavaScript()”方法,它位于我的窗口“BrowserWindow”中。 CallUI窗口在Helper.exe中声明并初始化。

所以基本上我试图使用单独的程序打开一个窗口,单击一个调用该方法并执行javascript的按钮。 所以我认为因为它们是不同的进程,它告诉我浏览器是null。 但是,当我在Main.exe中完成所有操作时,它可以正常工作。 是否有一种解决方法允许我使用单独的进程从Helper.exe创建窗口并从Main.exe执行Javascript?

我注意到我正在以错误的方式处理问题。

事实上,如果只是将所有代码放在一起的单个进程,我的问题就不存在了。 但是,我的项目有一个试图与另一个进行通信的可执行文件的事实是问题所在。 我实际上从来没有办法让我的helper.exe与我的main.exe正确对话。

我从中学到的是,这些进程试图在没有任何共享地址访问的情况下相互通信。 它们位于不同的地址空间中,因此每当我的helper.exe尝试执行属于Main.exe的javascript部分时,它就会尝试在属于其自己的地址空间而不是主要的浏览器的未初始化版本中执行该脚本。可执行程序。

那么我是如何解决这个问题的呢? 我必须包含一个重要的部分,允许helper.exe进程与main.exe进程通信。 当我搜索进程如何相互通信时,我发现了MemoryMappedFiles。 所以我决定在我的程序中实现一个简单的例子,允许Helper.exe向Main.exe发送消息。

这是一个例子。 这是我创建的一个名为“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,Main.exe和Helper.exe都可以使用。

Helper.exe使用PassMessage()方法将消息发送到名为“mmf1”的内存映射文件。 Main.exe必须始终打开,负责创建可以从Helper.exe接收消息的文件。 我将该Message发送到一个包含该消息的类,每次收到它时,它都会激活一个事件。

这是Message类的样子:

[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类中初始化Message,如下所示:

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');");
    }
}

现在,它允许我通过从Helper.exe向Main.exe发送消息来执行我需要的JavaScript。

你试过这个链接吗? 包含一个片段,用于检查浏览器是否首先初始化。

cefsharp执行javascript

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM