Chrome原生消息API chrome.runtime.connectNative不是一个函数。

10
我希望能够操作当前在Chrome标签页上的内容页面,如果以下内容不能实现这一点,那么我需要找到方法来实现!
大家好,我正在尝试让这个新的Chrome扩展程序与我的C#程序配合工作,以便彼此传递信息。我已经在stackoverflow上看过很多代码演示,这主要是我一直在依赖的,但似乎所有的例子都在我的端上不起作用。
我的问题是我遇到以下错误:
Connecting to native messaging host com.google.chrome.example.echo
Uncaught TypeError: chrome.runtime.connectNative is not a function

在这里输入图片描述

每当我尝试“连接”到端口时。

不确定我做错了什么,因为我已经按照这里的其他教程进行了跟随,它们似乎都声称可以工作....

JS主文件 main.js:

var port = null;
var getKeys = function (obj) {
    var keys = [];
    for (var key in obj) {
        keys.push(key);
    }
    return keys;
}
function appendMessage(text) {
    document.getElementById('response').innerHTML += "<p>" + text + "</p>";
}
function updateUiState() {
    if (port) {
        document.getElementById('connect-button').style.display = 'none';
        document.getElementById('input-text').style.display = 'block';
        document.getElementById('send-message-button').style.display = 'block';
    } else {
        document.getElementById('connect-button').style.display = 'block';
        document.getElementById('input-text').style.display = 'none';
        document.getElementById('send-message-button').style.display = 'none';
    }
}
function sendNativeMessage() {
    message = { "text": document.getElementById('input-text').value };
    port.postMessage(message);
    appendMessage("Sent message: <b>" + JSON.stringify(message) + "</b>");
}
function onNativeMessage(message) {
    appendMessage("Received message: <b>" + JSON.stringify(message) + "</b>");
}
function onDisconnected() {
    appendMessage("Failed to connect: " + chrome.runtime.lastError.message);
    port = null;
    updateUiState();
}
function connect() {
    var hostName = "com.google.chrome.example.echo";
    appendMessage("Connecting to native messaging host <b>" + hostName + "</b>")
    console.log("Connecting to native messaging host " + hostName);
    port = chrome.runtime.connectNative(hostName);
    port.onMessage.addListener(onNativeMessage);
    port.onDisconnect.addListener(onDisconnected);
    updateUiState();
}
document.addEventListener('DOMContentLoaded', function () {
    document.getElementById('connect-button').addEventListener(
        'click', connect);
    document.getElementById('send-message-button').addEventListener(
        'click', sendNativeMessage);
    updateUiState();
});

manifest.json文件:

{
  // Extension ID: knldjmfmopnpolahpmmgbagdohdnhkik
  "key": "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDcBHwzDvyBQ6bDppkIs9MP4ksKqCMyXQ/A52JivHZKh4YO/9vJsT3oaYhSpDCE9RPocOEQvwsHsFReW2nUEc6OLLyoCFFxIb7KkLGsmfakkut/fFdNJYh0xOTbSN8YvLWcqph09XAY2Y/f0AL7vfO1cuCqtkMt8hFrBGWxDdf9CQIDAQAB",
  "name": "Native Messaging Example",
  "version": "1.0",
  "manifest_version": 2,
  "description": "Send a message to a native application.",
  "app": {
    "launch": {
      "local_path": "main.html"
    }
  },
  "icons": {
    "128": "icon-128.png"
  },
  "permissions": [
    "nativeMessaging"
  ]
}

注册表:

REG ADD "HKCU\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /ve /t REG_SZ /d "%~dp0com.google.chrome.example.echo-win.json" /f

C#代码:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace talkWithChromeCSharp
{
    class Program
    {
        public static void Main(string[] args)
        {
            JObject data;
            while ((data = Read()) != null)
            {
                var processed = ProcessMessage(data);
                Write(processed);
                if (processed == "exit")
                {
                    return;
                }
            }
        }

        public static string ProcessMessage(JObject data)
        {
            var message = data["message"].Value<string>();
            switch (message)
            {
                case "test":
                    return "testing!";
                case "exit":
                    return "exit";
                default:
                    return "echo: " + message;
            }
        }

        public static JObject Read()
        {
            var stdin = Console.OpenStandardInput();
            var length = 0;

            var lengthBytes = new byte[4];
            stdin.Read(lengthBytes, 0, 4);
            length = BitConverter.ToInt32(lengthBytes, 0);

            var buffer = new char[length];
            using (var reader = new StreamReader(stdin))
            {
                while (reader.Peek() >= 0)
                {
                    reader.Read(buffer, 0, buffer.Length);
                }
            }

            return (JObject)JsonConvert.DeserializeObject<JObject>(new string(buffer))["data"];
        }

        public static void Write(JToken data)
        {
            var json = new JObject();
            json["data"] = data;

            var bytes = System.Text.Encoding.UTF8.GetBytes(json.ToString(Formatting.None));

            var stdout = Console.OpenStandardOutput();
            stdout.WriteByte((byte)((bytes.Length >> 0) & 0xFF));
            stdout.WriteByte((byte)((bytes.Length >> 8) & 0xFF));
            stdout.WriteByte((byte)((bytes.Length >> 16) & 0xFF));
            stdout.WriteByte((byte)((bytes.Length >> 24) & 0xFF));
            stdout.Write(bytes, 0, bytes.Length);
            stdout.Flush();
        }
    }
}

com.google.chrome.example.echo-win.json file:

{
  "name": "com.google.chrome.example.echo",
  "description": "Chrome Native Messaging API Example Host",
  "path": "native-messaging-example-host.bat",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
  ]
}

HTML main.html:

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <script src='main.js'></script>
</head>
<body>
    <button id='connect-button'>Connect</button>
    <input id='input-text' type='text' />
    <button id='send-message-button'>Send</button>
    <div id='response'></div>
</body>
</html>

我的Visual Studio目录结构:

C:\Users\t||||||\Documents\Visual Studio 2012\Projects\talkWithChromeCSharp\talkWithChromeCSharp
   -APP
     |-icon-128.png
     |-main.html
     |-main.js
     |-manifest.json
   -bin
     |-Debug
        |-Newtonsoft.Json.dll
        |-talkWithChromeCSharp.exe
        |-etc etc...
     |-Release
   -obj
   -Properties
   -regs
     |-com.google.chrome.example.echo-win.json
     |-install_host.bat
     |-etc etc...

在启动VS调试后,我安装了插件,并在Chrome浏览器上加载了main.html文件,然后点击“连接”按钮。这就是我遇到错误的时候。

我错过了什么吗?

更新

那是它的正确ID。我保持这样做,因为我猜“KEY”是决定ID的因素。

输入图像描述 输入图像描述


"allowed_origins": [ "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/" ]是从示例页面复制粘贴的,那你的扩展ID是什么?请尝试使用正确的ID。 - DannyZB
@DanielBatkilin,那是错误的。这是该密钥的正确ID。 - StealthRT
@Teepeemm,我已经更改了标签。感谢您指出。 - StealthRT
尝试从您的后台页面运行命令...似乎您确实没有设置此权限(我不确定为什么)->有时谷歌在不事先通知的情况下,在Chrome版本之间对API进行重大更改。 - DannyZB
1
这段代码可用于将本地应用程序文本发送到Chrome应用程序:https://gist.github.com/hubplace/9465a081c786fa0f685e - user285594
显示剩余3条评论
4个回答

10
太多的混淆和解释不清楚,这对我来说真的很有效。因此,我正在尝试制作一个“白痴证明”的文档。(请改进这个版本)
目标:Windows操作系统,已测试Google Chrome版本50,与本地应用程序通信。

步骤 1:


Download: https://developer.chrome.com/extensions/examples/api/nativeMessaging/app.zip

步骤2:


将下载的应用加载到Google Chrome中

enter image description here

第三步:

a) 添加注册表键

REG ADD "HKLM\Software\Google\Chrome\NativeMessagingHosts\com.google.chrome.example.echo" /ve /t REG_SZ /d "C:\\run-my-exe\\manifest.json" /f

enter image description here

b) 要创建自定义的Chrome执行器,请将以下内容复制到C:\ run-my-exe \ run-chrome.bat中:

"C:\ Program Files(x86)\ Google \ Chrome \ Application \ chrome.exe"--enable--native-messaging --native-messaging-hosts ="com.google.chrome.example.echo = C:\\ run-my-exe \\ manifest.json"

步骤4:主机


将以下内容放入 C:\run-my-exe\manifest.json。
{
  "name": "com.google.chrome.example.echo",
  "description": "Chrome Native Messaging API Example Host",
  "path": "native-messaging-example-host.bat",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://knldjmfmopnpolahpmmgbagdohdnhkik/"
  ]
}

b) 将以下内容放到 C:\run-my-exe\native-messaging-example-host.bat 中

@echo off
cd %windir%\system32
start calc.exe

步骤5:现在我该如何运行它?

a) 使用此脚本打开Chrome:C:\\run-my-exe\\run-chrome.bat

b) 在Chrome浏览器中输入chrome://apps

c) 通过图标启动

enter image description here

不是以下这样:

enter image description here

最终输出:

enter image description here


1
感谢这些说明。起初它对我没有用,但现在可以了。我之前尝试过该应用程序,并且在当前用户和本地机器中具有相同的注册表键。当前用户键是无效的。删除并重新运行后,我已经成功弹出计算器。一个问题,是否有任何方法可以使用参数调用exe文件? - JustAspMe
2
@YumYumYum,但是等等,Google不是要在2018年从Chrome中删除Chrome应用程序吗?请参见https://blog.chromium.org/2016/08/from-chrome-apps-to-web.html,换句话说,这在未来将不再起作用?我已经在https://docs.google.com/forms/d/e/1FAIpQLSenHdpA8_eqKiVOrWDjWe_KTfJmoSBEqFIh6SMwQ-NRDJnx1Q/viewform上提交了一个请求,希望将其包含在未来的版本中,但我们需要更多人告诉Chrome团队本地消息传递很重要。 - Pacerier
1
@YumYumYum,我们需要人们在这个表格https://docs.google.com/forms/d/e/1FAIpQLSenHdpA8_eqKiVOrWDjWe_KTfJmoSBEqFIh6SMwQ-NRDJnx1Q/viewform上进行垃圾邮件攻击,并告诉他们包括`connectNative`函数,否则Chrome团队将再次忽略我们。 - Pacerier
2
顺便说一句,第3b步骤是不必要的。我已经尝试过没有 --enable--native-messaging--native-messaging-hosts 的情况下运行,它可以正常工作。唯一需要的是注册表安装。 - Pacerier
1
@YumYumYum,看起来这个答案已经不再适用了。我收到了 ERROR:native_process_launcher.cc(147) Failed to load manifest for native messaging host com.google.chrome.example.echo: Invalid value for name. 的错误提示。对于你的环境,这个答案中提到的步骤还有效吗? - Pacerier
显示剩余3条评论

1

您不应该直接打开main.html文件,而是通过Chrome应用程序启动器在chrome://apps/处打开。


1
是的 - 从 chrome://apps/ 启动它可以工作。但是我该如何像 http://localhosthttps://myserver.com/sameapp 这样启动它,并以相同的方式连接? - user285594
1
我不是完全确定,但我认为你需要将应用程序添加到Chrome Web Store中,然后人们会在本地安装它。 - Chet
看到这个问题了吗,从 http:// 或 https:// 如何使用它从来没有被很好地记录下来。我需要使用它而不是使用 chrome://apps 的概念。 - user285594

0

由于您正在使用生成exe文件作为输出的C#项目,因此native-messaging-example-host.bat文件不应该像原始示例那样:

python "%~dp0/native-messaging-example-host" %*

相反,批处理文件应该更改如下:

@echo off
Pushd C:\Users\h.aghajani\Desktop\host  /*Path directory of your exe*/
start native-messaging-example-host.exe /*Name of the execution file*/

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接