Chrome Native Messaging 与本地程序之间的通信

   最近项目上出现了web打印不稳定的问题,师父决定web调用本地打印程序,在查阅了相关资料和加了几个相关群咨询后得知新版的chrome不支持NNAPI了,最好用Native Messaging来处理,经过一段时间的学习和试错,终于完成了,所以把步骤与总结发出来。过程参考http://blog.csdn.net/talking12391239/article/details/38498557

   首先,我们需要写一个chrome插件。学习相关知识可以去Chrome扩展及应用开发》这个插件包含了三个文件:manifest.json(这个是插件配置信息文件),background.js(文件名可改, 后台文件),content.js(与页面交互,传递消息给后台)。首先我们来看manifest.json这个文件,

 1 {  
 2     "name" : "myApp",  
 3     "version" : "1.0.1",  
 4     "description" : "Launch APP ",  
 5     "background" : { "scripts": ["background.js"] },  
 6   
 7     "permissions" : [  
 8         "nativeMessaging",  
 9         "tabs",  
10         "http://*/*"  
11     ],  
12     "content_scripts": [  
13     {  
14       "matches": ["http://*/*"],  
15       "js": ["content.js"]  
16     }  
17     ],  
18     "minimum_chrome_version" : "6.0.0.0",  
19     "manifest_version": 2  
20 }
21  

上面可以看出,这个文件在哪里引用了background.js和content.js,这两个文件的名字是可以更改的,permissions里的"http://*/*"与 content_scripts里的"matches"的意思是允许所有的http请求的url调用。"nativeMessaging" 代表要在这个插件中允许调用这种方法。

    接下来,看一下后台文件background.js:

 1 var port = null;   
 2 chrome.runtime.onMessage.addListener(  
 3   function(request, sender, sendResponse) {  
 4      if (request.type == "launch"){  
 5         connectToNativeHost(request.message);  
 6     }  
 7     return true;  
 8 });  
 9   
10   
11 //onNativeDisconnect  
12 function onDisconnected()  
13 {  
14     console.log(chrome.runtime.lastError);  
15     console.log('disconnected from native app.');  
16     port = null;  
17 }  
18   
19 function onNativeMessage(message) {  
20     console.log('recieved message from native app: ' + JSON.stringify(message));  
21 }  
22   
23 //connect to native host and get the communicatetion port  
24 function connectToNativeHost(msg)  
25 {  
26     var nativeHostName = "com.dhcc.lisprint";   
27     port = chrome.runtime.connectNative(nativeHostName); 
28     console.log(port)
29     port.onMessage.addListener(onNativeMessage);  
30     port.onDisconnect.addListener(onDisconnected);  
31     port.postMessage({message: msg});     
32  } 

   这个js文件里有两个十分重要的方法chrome.runtime.onMessage.addListener和connectToNativeHost。chrome.runtime.onMessage.addListener里可以看出,这个响应事件的方式为"launch"时,调用connectToNativeHost。

connectToNativeHost链接com.dhcc.lisprint这个服务。同时postMessage。

   接下来,我们来看content.js。

1 var launch_message;  
2 document.addEventListener('myCustomEvent', function(evt) { 
3   console.log(evt);
4   chrome.runtime.sendMessage({type: "launch", message: evt.detail}, function(response) {  
5   });  
6 }, false);

  这个文件的意图很明显,当界面传来myCustomEvent这个事件,向后台文件background.js发送type为launch的信息。


  以上就是chrome插件相关部分,我们可以看出并未写如何调用下面介绍native messaging调用部分。首先我们新建一个文件,manifest.json(名称可以修改)。

1 {
2     "name": "com.dhcc.lisprint",
3     "description": "Dhcc imedical lis print config app",
4     "path": "C:\Test.exe",
5     "type": "stdio",
6     "allowed_origins": [
7         "chrome-extension://acpcejomihdkopjnnijfmnpdgfkmfhkj/"
8     ]
9 }

可以很明显的看出,name即我们background.js里面要调用的host,path即我们要调用的本的应用程序。allowed_origins是什么呢?即我们安装完chrome插件的ID,如图:

那如何让chrome知道这个json就是com.dhcc.print的配置文件呢?这里我们还需要进行下一步,修改注册表:

运行-> Regedit -> HKEY_Current_User->Software->Google->Chrome->新建一个叫NativeMessagingHosts的项->新建一个叫com.my_company.my_application的项,  同时在这个项里默认值设置为我们Native Messaging 的 位置 即这个json文件的位置,如C:\Native\manifest.json。这样便完成了native masseging的设置。


接下来我们看界面是如何调用的

<html>
<head>
    <script>

function startApp() {
    var evt = document.createEvent("CustomEvent");
    evt.initCustomEvent('myCustomEvent', true, false, "哈哈哈哈");
    // fire the event
    document.dispatchEvent(evt);
}

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

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

下面,我们可以看下如何接收页面传递给exe的信息。

 1  private void Form1_Load(object sender, EventArgs e)
 2         {
 3             string chromeMessage = OpenStandardStreamIn();
 4 
 5             MessageBox.Show(chromeMessage);
 6 
 7         }
 8 
 9         private static string OpenStandardStreamIn()
10         {
11             //// We need to read first 4 bytes for length information  
12             Stream stdin = Console.OpenStandardInput();
13             int length = 0;
14             byte[] bytes = new byte[4];
15             stdin.Read(bytes, 0, 4);
16             length = System.BitConverter.ToInt32(bytes, 0);
17 
18             string input = "";
19             for (int i = 0; i < length; i++)
20             {
21                 input += (char)stdin.ReadByte();
22             }
23 
24             return input;
25         }

以上就是全部内容啦~


原文地址:https://www.cnblogs.com/real9527/p/4970858.html