zoukankan      html  css  js  c++  java
  • 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>
    非常easy, 响应了一个页面中的事件"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>

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

    -------------------------------------我是切割线-------------------------------------

    我们最后再来看看C#程序, 随便做一个很easy的程序, 放到了

    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;
            }
        }
    }


    
    

    点击我们在页面上增加的button, 然后检查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 

    我将不赘述

    版权声明:本文博客原创文章。博客,未经同意,不得转载。

  • 相关阅读:
    洛谷P2415 集合求和
    八数码难题解法大全
    P1789 【Mc生存】插火把
    P1554 梦中的统计
    CentOS6.4 安装 Oracle11g
    湖南省第八届大学生程序设计大赛原题 D
    选择排序(直接选择、堆排序)
    改变Emacs下的注释代码方式以支持当前行(未选中情况下)的注释/反注释
    cocos2d-x游戏开发(十五)游戏加载动画loading界面
    SIMPASS技术解析
  • 原文地址:https://www.cnblogs.com/yxwkf/p/4617903.html
Copyright © 2011-2022 走看看