You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展Native Messaging:JS向C#传递自定义数据失败的问题求助

Chrome扩展Native Messaging:JS向C#传递自定义数据失败的问题求助

兄弟,你这问题的核心是完全搞错了Chrome Native Messaging的通信机制!你现在用NamedPipeServerStream的方式完全不符合它的规范,这就是你只拿到奇怪的扩展ID字符串、真实数据传不过去的根本原因。

先给你划重点:Chrome Native Messaging不是通过命名管道通信,而是通过标准输入(stdin)和标准输出(stdout) 和你的C#程序交互,而且消息必须遵循严格的格式:先传4字节无符号小端整数(表示后续JSON数据的字节长度),再跟UTF-8编码的JSON字符串。

接下来一步步帮你修正问题:

1. 先搞定Native Messaging的系统配置(必须!)

Chrome需要知道你的Native Host的存在,以及哪些扩展可以和它通信。以Windows系统为例,你需要完成以下配置:

步骤1:创建Native Host的JSON配置文件

命名为com.my_company.my_application.json,内容如下:

{
  "name": "com.my_company.my_application",
  "description": "我的Native Messaging主机",
  "path": "C:\\你的C#程序路径\\NativeHost.exe",
  "type": "stdio",
  "allowed_origins": [
    "chrome-extension://你的扩展ID/"
  ]
}
  • 把path替换为你C#程序编译后exe文件的绝对路径
  • 把你的扩展ID替换为Chrome扩展的真实ID(在扩展管理页面开启开发者模式后就能看到)

步骤2:添加注册表项

打开注册表编辑器(regedit),导航到:
HKEY_CURRENT_USER\Software\Google\Chrome\NativeMessagingHosts\com.my_company.my_application
(路径不存在就手动创建)
然后将默认值设置为你刚才创建的JSON配置文件的绝对路径。

2. 重写你的C#代码(遵循Native Messaging协议)

把你的C#代码改成读取标准输入的内容,按照协议解析消息:

using System;
using System.IO;
using System.Text;
using System.Threading.Tasks;
using System.Text.Json;

namespace NativeMessagingHost
{
    class Program
    {
        static async Task Main(string[] args)
        {
            try
            {
                // 1. 读取消息长度前缀(Native Messaging强制要求的4字节小端整数)
                var lengthBuffer = new byte[4];
                await Console.OpenStandardInput().ReadAsync(lengthBuffer, 0, 4);
                // 转成无符号整数,注意小端字节序
                if (!BitConverter.IsLittleEndian)
                    Array.Reverse(lengthBuffer);
                uint messageLength = BitConverter.ToUInt32(lengthBuffer, 0);

                // 2. 读取对应长度的消息内容
                var messageBuffer = new byte[messageLength];
                await Console.OpenStandardInput().ReadAsync(messageBuffer, 0, (int)messageLength);
                string messageJson = Encoding.UTF8.GetString(messageBuffer);

                // 这里就能拿到你从JS发的dados对象了
                Console.WriteLine($"收到的消息:{messageJson}");
                // 可以转成对象处理
                var dados = JsonSerializer.Deserialize<dynamic>(messageJson);
                Console.WriteLine($"Nome: {dados.nome}, Idade: {dados.idade}");

                // 如果需要给JS返回响应,也要遵循同样的格式
                var response = new { status = "success", message = "数据已收到" };
                string responseJson = JsonSerializer.Serialize(response);
                byte[] responseBytes = Encoding.UTF8.GetBytes(responseJson);
                
                // 先写响应长度前缀
                byte[] responseLength = BitConverter.GetBytes((uint)responseBytes.Length);
                if (!BitConverter.IsLittleEndian)
                    Array.Reverse(responseLength);
                await Console.OpenStandardOutput().WriteAsync(responseLength, 0, 4);
                
                // 再写响应内容
                await Console.OpenStandardOutput().WriteAsync(responseBytes, 0, responseBytes.Length);
                await Console.OpenStandardOutput().FlushAsync();
            }
            catch (Exception ex)
            {
                // 调试日志不要输出到stdout(会破坏协议),可以写到文件
                File.WriteAllText("native_host_error.log", ex.ToString());
            }
        }
    }
}

代码关键说明:

  • 必须先读取4字节的长度前缀,这是Chrome Native Messaging的强制要求
  • 不要用Console.WriteLine直接输出内容到stdout,会破坏协议格式;调试信息可以写到本地文件或者用调试器查看
  • 返回响应时也要遵循“长度前缀+JSON内容”的格式

3. 你的JS代码基本没问题,注意两个细节

你的JS代码逻辑是正确的,但要确认:

  • chrome.runtime.sendNativeMessage的第一个参数(com.my_company.my_application)和配置文件里的name完全一致
  • 你的扩展ID已经正确添加到配置文件的allowed_origins中

再贴一遍你的JS代码(确认无误):

const dados = {
    nome: "João",
    idade: 30
};

chrome.runtime.sendNativeMessage(
    'com.my_company.my_application',
    dados,
    function(response) {
        if (chrome.runtime.lastError) {
            console.error("Error communicating with the native host:", chrome.runtime.lastError);
        } else {
            console.log('Response received: ', response);
        }
    }
);

4. 测试步骤

  1. 编译你的C#代码,生成exe文件
  2. 确认注册表、JSON配置文件的路径和扩展ID都正确
  3. 重新加载Chrome扩展(扩展管理页面点击“重新加载”)
  4. 触发你的JS代码(比如点击扩展按钮)
  5. 查看C#程序的调试日志或文件,应该能收到正确的{"nome":"João","idade":30}数据

为什么之前只拿到chrome-extension://<>?

因为你用了命名管道,Chrome的Native Messaging机制根本不会连接你的管道,反而你的程序可能误把Chrome启动它时传递的默认信息当成了消息,才出现了那个奇怪的字符串。


备注:内容来源于stack exchange,提问作者Leandro Bruscato

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 18:10:28