macos - 使用 Xamarin Mac、C# 的跨浏览器、跨平台 native 消息传递

标签 macos xamarin.forms chrome-native-messaging

我尝试重新创建示例以使用我将用作所有其他浏览器的主干的 chrome 扩展连接到我的 Xamarin Mac 应用程序,但它没有与以下错误一起工作:

与 native 消息传递主机通信时出错。

文档在纸上看起来很简单,但在现实生活中并不是那么简单。

这是我的阅读和收听功能(那里有很好的例子,https://github.com/anewtonlevey/NativeMessaging):

    public void Listen()
    {

        JObject data;
        while ((data = Read()) != null)
        {
            ProcessReceivedMessage(data);
        }

    }




    private JObject Read()
    {
        try
        {
            Stream stdin = Console.OpenStandardInput();


            byte[] lengthBytes = new byte[4];
            stdin.Read(lengthBytes, 0, 4);


            var buffer = new char[BitConverter.ToInt32(lengthBytes, 0)];

            using (var reader = new StreamReader(stdin)) while (reader.Peek() >= 0) reader.Read(buffer, 0, buffer.Length);
            return JsonConvert.DeserializeObject<JObject>(new string(buffer));


        }
        catch (Exception e)
        {
            Console.WriteLine("Read error: {0}", e);
            return null;
        }
    }

在我的 main 函数中,我使用以下命令调用它们:
        host = new ExtendedHost();


        host.Listen();

请注意,我正在为 macOS 应用程序使用来自 Xamarin 表单的 native 消息传递,从我的角度来看,它可能是字节序,如以下文档所示:

与 native 消息传递主机通信时出错:

https://developer.chrome.com/extensions/nativeMessaging#native-messaging-host-protocol

当我从 Web 扩展发送消息时,我的 C# 应用程序的另一个窗口似乎想要打开,这意味着错误似乎发生在阅读步骤。

非常感谢帮助。

谢谢。

编辑:

我建议使用字节顺序,因为文档表明响应也应该是正确的,否则会导致整个过程损坏,正如 中所建议的那样。 native 消息传递协议(protocol)文档 ,但这肯定不是问题,因为我仍然应该能够解析发送的数据:

https://developer.chrome.com/apps/nativeMessaging#native-messaging-host-protocol

我看到响应与它有关,并且用于发送消息的函数(因为有人建议响应错误可能导致整体错误)会导致问题,或者 Console.StandardInput() 不会按照建议工作,但我不这么认为。

我的想法是,当我使用 时,尝试附加到正在运行的应用程序会导致问题。 ps辅助| grep 应用程序名称 ,并将路径放在主机文件中。

这是协议(protocol)中的提及:

native 消息传递协议(protocol)
Chrome 在单独的进程中启动每个 native 消息传递主机,并使用标准输入 (stdin) 和标准输出 (stdout) 与其通信。


我还在另一篇文章中看到了 Xan 的回答,即 native 消息传递无法附加到正在运行的进程,Chrome 应该启动该进程:

Talk to MacOSX app from Chrome Extension

不要忘记我在 Debug模式下将 native 消息传递 API 与 Xamarin macOS 一起使用,并且我的应用程序是 macOS 应用程序。

欢迎提供有关该主题的更多信息,例如:
  • 一种获取应用程序路径的方法,Chrome 可以使用其原生消息 API
  • 以编程方式获取此路径的解决方案,如果可能,它将在所有平台上工作,如 Console.WriteLine(Path.Combine(Assembly.GetExecutingAssembly().Location)); 没有成功。

  • 当然,如果这是您认为导致问题的原因。

    提前致谢!

    编辑:

    将输出发送到 stderr 时,出现以下错误:

    读取错误:System.NotSupportedException:流不支持读取
    在/Library/Frameworks/Xamarin.Mac.framework/Versions/Current/src/Xamarin.Mac 中的 System.IO.FileStream.Read(System.Byte[] 数组,System.Int32 偏移量,System.Int32 计数)[0x0002e]/mcs/class/corlib/System.IO/FileStream.cs:493

    难道是 Console.OpenStandardInput 不能跨平台工作?
    如果是这样,解析标准输入的另一种方法可能是什么,因为我看到管道可以工作,但我不确定它们是否可以以跨平台方式部署。

    阅读时我没有收到任何错误或输出,只有在应用程序启动时出现上述错误。
    对我来说,OpenStandardInput 似乎是罪魁祸首。

    任何想法表示赞赏!谢谢

    最佳答案

    基本上,从扩展发送的前 32 位对应于消息长度,按 native 顺序。

    由于前 32 位是 int 类型,我尝试解析 JSON 对象,与 native 消息传递主机通信时出错 被提出。该文档提到该问题存在于损坏的 native 消息传递协议(protocol)中。

    最糟糕的是,我在 Python 示例中看到了它,但认为这是由做它的程序员实现的。

    我在 Stack Overflow 上偶然发现了这个帖子,它帮助确认了 (Chrome App fails to communicate with native host on windows)。

    要以更详细的方式调试 Chrome,请使用 启动 Chrome --enable-logging=stderr --v=1 在命令行中,所有的标准错误都会在那里输出。

    文档中提到了它,但是使用 C# 在这里和那里找到的示例不包括它们。

    如果我有时间,我将通过编辑此答案来确认这是问题所在,并提供代码以使其在 Visual Studio for macOS 上运行。

    编辑

    几天前我设法让这个工作。我修改了代码,使其在没有 while 循环的情况下工作,因为 StreamReader 读取标准输入直到结束,因此不请求 while 循环(这导致我以前的代码挂起)。
    SendMessage 方法也与其他示例中的其他方法不同。行数更少,而且工作得很好。

    我的工作示例:

    public void Listen()
    {
    
    
        JObject data;
    
        //while ((data = Read()) != null)
        //{
        //    ProcessReceivedMessage(data);
        //}
    
        if((data = Read()) != null)
        {
            string message = ProcessReceivedMessage(data);
            SendMessage(message);
        }
    }
    
    
        private JObject Read()
        {
    
            Stream stdin = Console.OpenStandardInput();
    
            byte[] lengthBytes = new byte[4];
            stdin.Read(lengthBytes, 0, lengthBytes.Length);
    
            char[] buffer = new char[BitConverter.ToInt32(lengthBytes, 0)];
    
            var reader = new StreamReader(stdin);
            //int messageLength =
            reader.Read(buffer, 0, buffer.Length);
    
            return JsonConvert.DeserializeObject<JObject>(new string(buffer));
        }
    
    
    
    
    
        public void SendMessage(JToken data)
        {
            var bytes = Encoding.UTF8.GetBytes(data.ToString(Formatting.None));
            var lengthBytes = BitConverter.GetBytes(bytes.Length);
            var stdout = Console.OpenStandardOutput();
    
            stdout.Write(lengthBytes, 0, 4);
            stdout.Write(bytes, 0, bytes.Length);
            stdout.Flush();
        }
    

    关于macos - 使用 Xamarin Mac、C# 的跨浏览器、跨平台 native 消息传递,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60158354/

    相关文章:

    c - 有没有办法将控制台窗口永久附加到主 XCode 窗口?

    google-chrome - 在 Selenium ChromeDriver 中使用 native 消息传递?

    google-chrome-extension - 将 Google Chrome 扩展程序限制为选择平台

    xcode - 如何知道应用程序是否首次在 Mac 上运行

    macos - 尝试使用 OSX 使用 schemacrawler 连接到 sqlite 数据库 - 为什么它要求用户?

    c# - Xamarin.Forms 在运行时加载 XAML View

    c# - Xamarin 中 QR 扫描后的处理对话框

    javascript - 如何在 Firefox 附加组件中向子进程发送消息,如 Chrome native 消息传递

    macos - 如何在 emacs -nw/gui-less 模式下插入复选标记

    xamarin - 更改 xamarin 表单 android 中 ListView 的上下文操作菜单背景的颜色