Information interaction between chrome plug-in and local exe program

 

I. Overview

        If we want to communicate between the local exe program and the chrome plug-in, we need to use NativeMessage.

        See below for the specific environment and implementation steps.

2. Environment

        1. window10 operating system

        2. chrome browser

        3. pycharm

3. Implementation steps

        1. Write a chrome plug-in yourself

                For the detailed steps and file structure of chrome plug-in development, please refer to one of Chrome extension development - File structure of Chrome extension - Rock Sugar Snow Pear Without Water - Blog Garden (cnblogs.com) https://www.cnblogs.com/ligerleng/p/ gmail_assist_1.html                 Here we need to use the background, content_scripts and manifest.json files, and use Test.html for testing. The file code is as follows.

(1) Code in manifest.json

{ 
   "name" : "FastRun",  //插件名字
    "version" : "1.0.1",  //插件版本号
    "description" : "Launch APP ",   //对插件的描述

    "background" : {    //background的具体引用
     "scripts": ["background.js"] //这里引用js文件background.js
     }, 

    "content_scripts": [  //content_scripts的具体引用
    { 
       //mathes指明哪些网站可以使用content.js 
      "matches": [ "http://*/*", "https://*/*", "ftp://*/*", "file://*/*" ], 
      "js": ["content.js"]  //这里引用js文件content.js
    }  
    ],  

    //permissons是插件的权限,如果要使用nativeMessage就必须在其中加入nativeMessaging
    "permissions" : ["nativeMessaging", "tabs"],  
    "minimum_chrome_version" : "6.0.0.0",  
    "manifest_version": 2  
}

  (2) Code in content.js

var launch_message;
for (let i = 1; i <= 4; i++) {
//监听,只有监听到来自页面的"myCustomEvent1""myCustomEvent2""myCustomEvent3"...事件才触发
  document.addEventListener('myCustomEvent' + i, function (evt) {
    //向background.js发送信息
    chrome.runtime.sendMessage({
      type: "用户点击了按钮",
      message: evt.detail
    }, function (response) {});
  }, false);
}
//接收来自background.js的消息
chrome.runtime.onMessage.addListener(
  function (request, sender, sendResponse) {
    const message = document.querySelector('.message'); //获取message
    const newH3 = document.createElement('h3'); //创建一个h3标签
    newH3.innerHTML = request; //h3标签的内容为background.js发的消息
    message.appendChild(newH3) //把创建的h3标签添加到message中
    return true;
  });

(3) Code in background.js

var port = null;
//监听来自content.js的信息
chrome.runtime.onMessage.addListener(
  function (request, sender, sendResponse) {
    //request就是content.js发送过来的消息
    if (request.type == "用户点击了按钮") {
      connectToNativeHost(request.message);
    }
    return true;
  });


//断开连接时触发
function onDisconnected() {
  console.log(chrome.runtime.lastError);
  port = null;
}

//接收到来自exe程序的消息时触发
async function onNativeMessage(message) {
  console.log('接收到从本地应用程序发送来的消息:' + JSON.stringify(message));
  const tabId = await getCurrentTabId()
  chrome.tabs.sendMessage(tabId, JSON.stringify(message), function (response) {});
}

//得到当前tabId
function getCurrentTabId() {
  return new Promise((resolve, reject) => {
    chrome.tabs.query({
      active: true,
      currentWindow: true
    }, function (tabs) {
      resolve(tabs.length ? tabs[0].id : null)
    });
  })
}

//连接到本地主机并获得通信端口
function connectToNativeHost(msg) {
  var nativeHostName = "com.my_company.my_application"; //本地主机名(就是在注册表中的名字)
  port = chrome.runtime.connectNative(nativeHostName); //根据本地主机名得到通信端口
  port.onMessage.addListener(onNativeMessage); //监听exe程序是否发来消息
  port.onDisconnect.addListener(onDisconnected); //监听是否断开连接
  port.postMessage(msg) //向应用程序发送信息
}

 (4) Code in Test.html

<html>
<style>
  .message {
    width: 500px;
    height: 500px;
    background-color: pink;
  }

  h3 {
    background-color: red;
  }
</style>

<head>
  <script>
    function startApp(i) {
      //创建CustomEvent事件
      var eventName = "myCustomEvent" + i;
      var evt = document.createEvent("CustomEvent");
      evt.initCustomEvent(eventName, true, false, "用户点击了按钮" + i);
      //执行自定义事件
      document.dispatchEvent(evt);
    }
  </script>
</head>

<body>

  <button type="button" onClick="startApp(1)" id="startApp">按钮1</button>
  <button type="button" onClick="startApp(2)" id="startApp">按钮2</button>
  <button type="button" onClick="startApp(3)" id="startApp">按钮3</button>
  <button type="button" onClick="startApp(4)" id="startApp">按钮4</button>
  <div class="message">
    <h1 class="jieshou">接收到的消息:</h1>
  </div>
</body>

</html>

2. Install the chrome plug-in you wrote into the chrome browser

(1) Put the 4 files created above in the same folder and name them arbitrarily

(2) Enter: chrome://extensions in the chrome browser address bar   to enter the plug-in management page

(3) Open "Developer Mode" in the upper right corner

(4) Click "Load Unzipped Extension" in the upper left corner, select the folder where the 4 files are located and add

(5) You can see that the plug-in has been installed in the Chrome browser, as shown below (Each plug-in will automatically generate a unique ID value. We need to save the ID value of the plug-in we wrote. We will use it below, remember to save it! !!)

923acf4bd5c04b27806b59bdc22a2cea.png

 

 3. Create Test.py and write code

Open pycharm and create a Test.py file with the following code: (If there is no corresponding package, you need to import the corresponding package first)

import json
import sys
import struct
# 读取来自 stdin 的消息并对其进行解码
def get_message():
    raw_length = sys.stdin.buffer.read(4)
    if not raw_length:
        sys.exit(0)
    message_length = struct.unpack('=I', raw_length)[0]
    message = sys.stdin.buffer.read(message_length).decode("utf-8")
    return json.loads(message)

# 根据信息的内容对信息进行编码以便传输。
def encode_message(message_content):
    encoded_content = json.dumps(message_content).encode("utf-8")
    encoded_length = struct.pack('=I', len(encoded_content))
    #  use struct.pack("10s", bytes), to pack a string of the length of 10 characters
    return {'length': encoded_length, 'content': struct.pack(str(len(encoded_content))+"s",encoded_content)}

# 向标准输出发送编码好的消息
def send_message(encoded_message):
    sys.stdout.buffer.write(encoded_message['length'])
    sys.stdout.buffer.write(encoded_message['content'])
    sys.stdout.buffer.flush()

# 持续监听chrome插件发来的消息
while True:
    message = get_message() # 得到来自chrome插件的消息
    if(message=="用户点击了按钮1"): # 根据消息的不同内容,exe程序向chrome插件发送不同的字符串
        send_message(encode_message("来自exe程序的消息:按钮1被点击"))
    elif(message=="用户点击了按钮2"):
        send_message(encode_message("来自exe程序的消息:按钮2被点击"))
    elif(message=="用户点击了按钮3"):
        send_message(encode_message("来自exe程序的消息:按钮3被点击"))
    elif(message=="用户点击了按钮4"):
        send_message((encode_message("来自exe程序的消息:按钮4被点击")))

4. Package Test.py into an exe program

     Enter in the pycharm terminal:   pyinstaller -F Test.py (if there is no pyinstaller package, a pilot package is required)

Then the packaged exe program is in the dist folder under the folder where Test.py is located, and the file name is Test.exe

5. Write the Test.exe program into the registry

(1) First, you need to create a file named manifest.json (this file is different from the manifest.json file created above, but the name is the same. Don’t forget to replace the string under allowed_origins with the ID value of the plug-in you wrote!! !), where the code is:

{
    "name": "com.my_company.my_application",  //此名就是hostName,即主机名
	"description": "Chrome sent message to native app.", //对json文件的描述
	"path": "Test.exe",  //相对路径,打包好的Test.exe相对于本manifest文件的相对路径
	"type": "stdio",     //必填项,意为通过标准输入输出流进行通信
	"allowed_origins": [
		"chrome-extension://jckgmlnngpemfhapkfdapedimdpimlmd/" //中间的字符串是我们编写的插件的ID值,需要自己替换
	]
}

(2) Hold down the win+r keys to open the running windows command window, enter regedit to enter the registry editor, find the HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts directory, right-click NativeMessagingHosts, select New, select the item, and create a new file named com.my_company.my_application (the name is the host name, and the name should be the same as the name value of the manifest.json above), then select the new item, double-click the default on the right, and modify the numerical data to the manifest created for the second time. The absolute path of the .json file on this machine. See the figure below for specific operation steps.

73ab166e8bd9430e820ef45e0aca3548.png

 

5c5225e764004d8c927b7d3c7832eb7c.png

 6. Test

After completing the above steps, open the Test.html created above. Four buttons will appear. Click any button. The chrome plug-in will send a message to the exe program. After receiving the message, the exe program returns the corresponding value according to the message and appears below. As shown below6404c93b0d984cd6b1899be264978f43.png

 7. Supplement

The content output in content.js in the plug-in will be printed on the console of the current page (you can find the console by pressing the F12 key on the keyboard). You can add printing information for debugging.

The content output in background.js in the plug-in will be printed in the console of the background page of the current plug-in (enter chrome://extensions in the address bar of the chrome browser, find the plug-in you wrote, and click on the background page to find the console). You can add print information yourself for debugging.

 

Well, this article ends here! If you like it, remember to give me a like! If you have any other questions, please leave a message in the comment area!

 

 

Guess you like

Origin blog.csdn.net/weixin_68540347/article/details/128530077