Chrome 插件: 起动本地应用 (Native messaging)
Chrome 插件: 起动本地应用 (Native messaging)
最近碰到了一个新问题,需要利用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
在这里就不再赘述了
- 4楼yhdufei昨天 16:10
- 谢谢大侠,真心的非常感谢,亲自给我调试程序,终于可以了。
- 3楼qq_18649531昨天 17:49
- 可以贴一上示例代码吗?非常期待
- Re: Nicolas_008昨天 22:57
- 回复qq_18649531n已经加入了C#部分的测试代码
- 2楼yhdufei昨天 17:44
- 这位大侠,我一步一步的照着做,可怎么都启不动那个应用程序。可否加您的QQ,指导兄弟一下呢...我找这个资料找了很久了,好不容易找到您这份详细的介绍。369569334,跪求,重谢!付费亦可!
- 1楼u011441796昨天 13:53
- 好厉害的样子。