Chrome 插件: 起动本地应用 (Native messaging)

本文介绍如何通过Chrome插件启动本地C#应用程序,并实现数据传递。涉及关键步骤包括:构建Chrome插件、配置Native Messaging、注册Windows注册表项及实现C#应用的数据接收。

转自:http://www.myexception.cn/internet/1729118.html

最近碰到了一个新问题,需要利用Chrome 的插件, 从我们的一个网站中启动一个我们的本地C#应用,同时给这个应用传值来进行不同的操作。

在这里记录下解决的过程,以便以后查找


首先我们需要新建一个google的插件 这个插件包含了三个文件

manifest.json(名字不可改, 建插件必须文件),background.js(文件名可改, 后台文件),content.js(content script文件 负责与网站页面交互)

首先我们来看看manifest.json 这个文件

<span style="font-family:SimSun;font-size:18px;">{
	"name" : "FastRun",
	"version" : "1.0.1",
	"description" : "Launch APP ",
	"background" : { "scripts": ["background.js"] },

	"permissions" : [
		"nativeMessaging",
		"tabs",
		"http://xxx/*"
	],
	"content_scripts": [
    {
      "matches": ["http://xxx/*"],
      "js": ["content.js"]
    }
	],
	"minimum_chrome_version" : "6.0.0.0",
	"manifest_version": 2
}</span>

里面的premissions非常重要, 他表示我们的插件在什么条件运行, "nativeMessaging" 代表要在这个插件中允许调用这种方法

 "xxx"填入你想要的载入的网址 

"content_scripts" 中"xxx" 表示在什么网页下运行我们与界面交互的script.


再来看看后台文件

background.js

var port = null; 
chrome.runtime.onMessage.addListener(
  function(request, sender, sendResponse) {
     if (request.type == "launch"){
       	connectToNativeHost(request.message);
    }
	return true;
});


//onNativeDisconnect
function onDisconnected()
{
	console.log(chrome.runtime.lastError);
	console.log('disconnected from native app.');
	port = null;
}

function onNativeMessage(message) {
	console.log('recieved message from native app: ' + JSON.stringify(message));
}

//connect to native host and get the communicatetion port
function connectToNativeHost(msg)
{
	var nativeHostName = "com.my_company.my_application";
	console.log(nativeHostName);
 	port = chrome.runtime.connectNative(nativeHostName);
	port.onMessage.addListener(onNativeMessage);
	port.onDisconnect.addListener(onDisconnected);
	port.postMessage({message: msg});	
 } 


在这个文件里有两个方法非常重要 

chrome.runtime.onMessage.addListener

connectToNativeHost

先来看第一个方法,

是一个响应事件,当接收到类型为"launch"的消息时, 调用 connectToNativeHost方法并传入数据。

com.my_company.my_application

这个是我们之后需要注册在Regestry和Native Messaging里面的名字 之后会讲到。

runtime.connectNative这个方法连接我们的Native Messaging然后利用 postMessage 去发送我们要的信息给我们的本地应用

当然这里我们可以替换为 sendNativeMessage 直接给本地应用传值详见

https://developer.chrome.com/extensions/runtime#method-connectNative

我们在来看看ContentScript: content.js这个文件

 

<span style="font-family:SimSun;"><span style="font-size:18px;">var launch_message;
document.addEventListener('myCustomEvent', function(evt) {
chrome.runtime.sendMessage({type: "launch", message: evt.detail}, function(response) {
  console.log(response)
});
}, false);</span><strong>
</strong></span>
很简单, 响应了一个页面中的事件"myCustomEvent", 同时发布一个消息给我们的后台文件background.js,这个消息包含了消息标示 "launch" 和 我们要传的值 evt.detail

关于Content Script 的信息 详见 https://developer.chrome.com/extensions/content_scripts

到这里我们的google插件部分就做好了

别忘了在Chrome 插件里开启开发者模式 并加载这个插件

-------------------------------------分割线-------------------------------------


我们在来看看 Native Messaging 部分 我们再建一个 json 文件 我这里也叫做manifest.json(名字可以不是这个) 存在了我本地C:/Native目录下

<span style="font-family:SimSun;font-size:18px;">{
	"name": "com.my_company.my_application",
	"description": "Chrome sent message to native app.",
	"path": "C:\\MyApp.exe",
	"type": "stdio",
	"allowed_origins": [
		"chrome-extension://ohmdeifpmliljjdkaehaojmiafihbbdd/"
	]
}</span>

这里我们定义了 Native Messaging 的名字, 在path中定义了我们要运行的本地应用程序, allowed_origins 中长串的字符是我们插件的id 可以在安装插件后从google chrome 插件里看到(安装插件 可以在chrome中插件开启开发者模式并载入我们之前的插件文件包)


完成这步以后我们需要在WIndows 注册表 中加入google 项目具体如下:

运行-> Regedit -> HKEY_Current_User->Software->Google->Chrome->新建一个叫NativeMessagingHosts的项->新建一个叫com.my_company.my_application的项,  同时在这个项里默认值设置为我们Native Messaging 的 位置 C:\\Native\\manifest.json


这样我们就完成了NativeMessaging的设置

-------------------------------------我是分割线-------------------------------------

我们再来看看这个插件如何和我们的网站交互

先建一个简单的网页内容如下

<span style="font-family:SimSun;font-size:18px;"><!DOCTYPE HTML>

<html>
<head>
<script>
function startApp() {
	var evt = document.createEvent("CustomEvent");
	evt.initCustomEvent('myCustomEvent', true, false, "im information");
	// fire the event
	document.dispatchEvent(evt);
}

</script>
</head>
<body>

<button type="button" onClick="startApp()" id="startApp">startApp</button>
</body>
</html>
</span>

里面有一个简单的按钮, 这个按钮会启动方法, 新建一个名叫"myCustomEvent"的事件, 同时附带有我们要传的信息, 并发布这个事件。 这样我们插件中的Content.js 就可以接收并响应这个事件了!

-------------------------------------我是分割线-------------------------------------

我们最后再来看看C#程序, 随便做一个非常简单的程序, 放到了

C://MyApp.exe这里

在Main里面 我们可以加入下面这个方法, 利用Console.OpenStandardInput这个 我们可以接收到由页面传到我们应用的值并进行我们想要的一些操作, 在这里我们用一个log4net 记录我们程序运行情况

[assembly: log4net.Config.XmlConfigurator(Watch = true)]
namespace MyApp
{
    static class Program
    {
        public static log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
        [STAThread]
        static void Main(string[] args)
        {
            
            if (args.Length != 0)
            {
                string chromeMessage = OpenStandardStreamIn();
                log.Info("--------------------My application starts with Chrome Extension message: " + chromeMessage + "---------------------------------");
	        }
	    }

        private static string OpenStandardStreamIn()
        {
            //// We need to read first 4 bytes for length information
            Stream stdin = Console.OpenStandardInput();
            int length = 0;
            byte[] bytes = new byte[4];
            stdin.Read(bytes, 0, 4);
            length = System.BitConverter.ToInt32(bytes, 0);

            string input = "";
            for (int i = 0; i < length; i++)
            {
                input += (char)stdin.ReadByte();
            }

            return input;
        }
    }
}



点击我们在页面上加入的按钮, 然后检查log文件:


2014-07-30 09:23:14,562 [1] INFO  MyApp.Program ----------------------------------------My application starts with Chrome Extension message: {"message":"im information"}---------------------------------




最后一张图总结下整个过程


如果想要在安装我们本地软件时安装这个插件, 我们需要把我们的插件先发布到Chrome web store上详见https://developer.chrome.com/extensions/external_extensions 

在这里就不再赘述了

在开发 Chrome 插件时,若希望实现与本地应用程序的通信(Native Messaging),可以通过 `chrome.runtime.connectNative` 或 `chrome.runtime.sendNativeMessage` 方法来建立连接并传递消息。该机制允许扩展程序与本机应用进行双向通信[^1]。 ### 实现监听本地消息的基本结构 #### 1. 配置 Native Messaging Host 首先,需要配置一个 Native Messaging Host,它是一个独立运行在操作系统上的原生应用,能够与 Chrome 扩展交互。其主要职责包括: - 启动后等待来自扩展的消息。 - 读取标准输入流中的 JSON 格式消息。 - 处理请求并将响应通过标准输出返回给扩展。 Host 的可执行文件路径需注册到系统中,并通过 `manifest.json` 文件指定其权限和行为。 示例 `native-messaging-host.json` 内容: ```json { "name": "com.example.nativehost", "description": "Example Native Messaging Host", "path": "/path/to/native/host/executable", "type": "stdio", "allowed_origins": [ "chrome-extension://<your_extension_id>/" ] } ``` 将此文件放置在系统的 Native Messaging 注册目录下(如 macOS 中为 `~/Library/Application Support/Google/Chrome/NativeMessagingHosts/`)[^1]。 #### 2. 扩展端代码设置 在扩展中,可以使用如下方式连接 Native Messaging Host 并监听其响应: ##### 使用 `connectNative` 建立持久连接 ```javascript const port = chrome.runtime.connectNative('com.example.nativehost'); port.onMessage.addListener((response) => { console.log("Received: " + JSON.stringify(response)); }); port.onDisconnect.addListener(() => { console.log("Disconnected from native host."); }); port.postMessage({ text: "Hello from extension" }); ``` ##### 使用 `sendNativeMessage` 发送一次性请求 ```javascript chrome.runtime.sendNativeMessage( 'com.example.nativehost', { ping: "Ping from extension" }, function(response) { if (chrome.runtime.lastError) { console.error(chrome.runtime.lastError.message); } else { console.log("Response: " + JSON.stringify(response)); } } ); ``` #### 3. 本地 Host 程序逻辑(以 Python 为例) 以下是一个简单的 Python 脚本,用于作为 Native Messaging Host 接收消息并返回响应: ```python import sys import json def read_message(): raw_length = sys.stdin.buffer.read(4) if not raw_length: return None length = int.from_bytes(raw_length, byteorder='little') message = sys.stdin.buffer.read(length).decode('utf-8') return json.loads(message) def send_message(message): encoded = json.dumps(message).encode('utf-8') length = len(encoded) sys.stdout.buffer.write(length.to_bytes(4, byteorder='little')) sys.stdout.buffer.write(encoded) sys.stdout.buffer.flush() while True: message = read_message() if message is None: break print(f"Received: {message}") send_message({"echo": message}) ``` 此脚本将持续监听来自扩展的消息,并回传一个包含原始内容的响应对象[^1]。 ### 注意事项 - **调试与错误处理**:如果出现“pipe broken”等错误,通常意味着本地主机提前关闭了连接或未正确启动。应确保本地主机程序具有良好的异常捕获机制,并能稳定运行。 - **安全性**:确保只允许特定的扩展访问 Native Messaging Host,避免恶意扩展滥用。 - **兼容性**:不同平台下的 Native Messaging Host 实现可能略有差异,建议分别测试 Windows、macOS 和 Linux 上的行为。 ---
评论 8
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值