chrome插件与本地exe程序之间的信息交互

article/2025/11/9 16:31:56

 

一、概述

        如果想要通过本地exe程序与chrome插件之间的通信,我们需要利用到NativeMessage。

        具体环境与实现步骤见下文。

二、环境

        1. window10操作系统

        2. chrome浏览器

        3. pycharm

三、实现步骤

        1. 自己编写一个chrome插件

                chrome插件的开发详细步骤与文件结构可参考Chrome扩展开发之一——Chrome扩展的文件结构 - 冰糖雪梨不加水 - 博客园 (cnblogs.com)https://www.cnblogs.com/ligerleng/p/gmail_assist_1.html                这里我们需要用到background、content_scripts与manifest.json文件,并使用Test.html进行测试。文件代码如下。

(1)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) 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'); //获取messageconst newH3 = document.createElement('h3'); //创建一个h3标签newH3.innerHTML = request; //h3标签的内容为background.js发的消息message.appendChild(newH3) //把创建的h3标签添加到message中return true;});

(3)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) 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.把自己写的chrome插件安装到chrome浏览器中

(1)把上述创建的4个文件放在同一个文件夹中,命名任意

(2)在chrome浏览器地址栏输入:chrome://extensions  进入插件管理页面

(3)打开右上角《开发者模式》

(4)点击左上角《加载已解压的扩展程序》,选择4个文件所在的文件夹并添加

(5)就可以看到插件已经被安装到chrome浏览器当中,如下图 (每个插件都会自动生成一个独一无二的ID值,我们需要保存自己编写插件的ID值,下面需要用到,记得保存!!!)

923acf4bd5c04b27806b59bdc22a2cea.png

 

 3. 创建Test.py并写入代码

打开pycharm,创建Test.py文件,其中代码如下:(没有相应包的话需要先导入相应的包)

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 charactersreturn {'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.把Test.py打包成exe程序

     在pycharm终端中输入:  pyinstaller -F Test.py (如果没有pyinstaller包的需要先导包)

然后打包好的exe程序就在Test.py所在文件夹下的dist文件夹中,文件名为Test.exe

5.将Test.exe程序写入注册表

(1)首先需要创建一个文件,名为manifest.json(此文件不同于上面创建的manifest.json文件,只是名字一样 , 不要忘记把allowed_origins下的字符串替换成自己所写插件的ID值 !!!),其中代码为:

{"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)按住 win+r 键打开运行windows命令窗口,输入 regedit 进入注册表编辑器,找到HKEY_CURRENT_USER\SOFTWARE\Google\Chrome\NativeMessagingHosts 目录,右键单击NativeMessagingHosts,选择新建,选择项,新建一个名为 com.my_company.my_application 的项(该名就是主机名,名字应与上面那个manifest.json的name值相同),然后选中该新建的项,双击右侧默认,修改数值数据为第二次创建的manifest.json文件在本机的绝对路径,具体操作步骤见下图

73ab166e8bd9430e820ef45e0aca3548.png

 

5c5225e764004d8c927b7d3c7832eb7c.png

 6. 测试

完成上述步骤,打开上面创建的 Test.html,出现四个按钮,单击任意一个按钮,chrome插件将向exe程序发送消息,exe程序接收到消息后根据消息返回对应的值并出现在下方。如下图所示6404c93b0d984cd6b1899be264978f43.png

 7.补充

插件当中content.js中输出的内容会被打印在当前页面的控制台(按下键盘F12键即可找到控制台),可以自己添加打印信息进行调试。

插件当中background.js中输出的内容会被打印在当前插件的背景页的控制台中(chrome浏览器地址栏输入chrome://extensions,找到自己写的插件,点击背景页就可以找到控制台),可以自己添加打印信息进行调试。

 

好了,本篇文章就到此结束啦!如果喜欢记得给我点个赞哦!有其他任何疑问信息可以在评论区留言咨询!

 

 


http://chatgpt.dhexx.cn/article/OWIggtXJ.shtml

相关文章

win10更新后 chrome内核浏览器总是打开网页一直加载 甚至打不开 解决方法

升级win10之后如果出现chrome内核的浏览器网页总是打不开 打开很慢 而ie和edge是可以正常访问的 用这个方法可以 我弄了几天终于 搞好了 我直接转载过来了 近期&#xff0c;工程师收到大量反馈360浏览器&#xff0c;极速模式无法打开网页&#xff0c;兼容模式无此问题。 IE浏览…

客户端工具登录异常问题分析

1、首先判断是用户名密码是否错了&#xff1b; 2、在用户名密码正确的前提下&#xff0c;需要查看oninit程序的权限是否正确。如果权限异常&#xff0c;也会存在上述问题的 1、通常可以理解成informix弱口令的问题&#xff0c;调整弱口令之后&#xff0c;等几分钟即可

(十)服务端异常退出

&#xff08;十&#xff09;服务端异常退出 之前讲解了客户端异常退出的代码&#xff0c;但是服务端也是会异常退出的。如果服务端异常退出&#xff0c;它会将所有在线的客户的状态都设置为offline。即&#xff0c;让所有用户都下线。 异常退出一般是CTRL C时&#xff0c;我们…

统一异常处理 GlobalExceptionHandler

平时经常在代码里面 try {... } catch (Exception e) {... }这样子代码繁琐而且也不好看。特别是还有一些需要自己new一个map封装业务的异常信息&#xff0c;是在是难看。所以就需要引出全局异常。经过一些封装&#xff0c;就可以实现这样的效果了。 还是看代码吧&#xff01…

【异常】使用ApiFox客户端提示 “ 加载出错,请检查网络是否异常”,但是Web端是正常访问的

一、报错内容 提示内容类似于如下&#xff1a;连接Apifox服务器出错&#xff0c;请检查网络是否异常 二、报错说明 可能是因为APIFOX升级版本了&#xff0c;导致的问题&#xff0c;目前没有找到根因 三、报错解决 3.1 解决方案 1 使用Chrome的插件——Apifox Agent&#…

(七)客户端异常退出事件处理

如果客户端异常退出了&#xff0c;我们会从服务端记录用户连接的 _connMap 表中找到改用户&#xff0c;如果它断连了就从此表中删除&#xff0c;并设置其状态为 offline。 因为记录用户连接情况的表是可能被多个线程操作的&#xff0c;所以访问表的操作都要使用互斥锁进行保护。…

彻底解决aapt2异常

随时随地阅读更多技术实战干货&#xff0c;获取项目源码、学习资料&#xff0c;请关注源代码社区公众号(ydmsq666) from&#xff1a;https://blog.csdn.net/qq_34879948/article/details/80313690 升级android studio 3.0后&#xff0c;在创建新项目时会报一个异常&#xff0c…

客户端异常的处理

在我们的项目中&#xff0c;我们一般只会捕获我们自己能够想到的异常&#xff0c;但是这样就会导致一些无法捕捉到的异常被漏出去&#xff0c;因为我们不能确定它们会在什么地方出现&#xff0c;例如像NullPointerException&#xff0c;ClassCastException&#xff0c;IndexOut…

2021年6月大学英语六级作文

目录 1.第一套 2.第二套 3.第三套 1.第一套 中国高等教育∶Directions∶For this part&#xff0c; you are allowed 30 mimites to write an essay based on the chart below.You should start your essay with a brief description of the chart and comment on Chinas ac…

【人工智能】大模型平台新贵——文心千帆

个人主页&#xff1a;【&#x1f60a;个人主页】 &#x1f31e;热爱编程&#xff0c;热爱生活&#x1f31e; 文章目录 前言大模型平台文心千帆发布会推理能力模型微调 作用 前言 在不久的之前我们曾讨论过在ChatGPT爆火的大环境下&#xff0c;百度推出的“中国版ChatGPT”—文…

你如何看待百度的文心一言ERNIE Bot?心有所系,言出必行。

心有所系&#xff0c;言出必行。 排队中。。。 文心一言 百度全新一代知识增强大语言模型&#xff0c;文心大模型家族的新成员&#xff0c;能够与人对话互动&#xff0c;回答问题&#xff0c;协助创作&#xff0c;高效便捷地帮助人们获取信息、知识和灵感。 文心一言&#x…

Matcher: Segment Anything with One Shot Using All-Purpose Feature Matching 论文精读

Matcher: Segment Anything with One Shot Using All-Purpose Feature Matching 论文链接&#xff1a;[2305.13310] Matcher: Segment Anything with One Shot Using All-Purpose Feature Matching (arxiv.org) 代码链接&#xff1a;aim-uofa/Matcher: Matcher: Segment Anyt…

【问题记录】关于百度网盘客户端打不开

问题描述 双击桌面图标没有任何反应&#xff0c;用管理员模式也是没什么反应。 问题追踪 按ctrlshiftesc打开任务管理器&#xff0c;查看到百度网盘的一个升级程序在运行中&#xff0c;注意升级程序的网络一栏&#xff0c;表明该进程在下载东西&#xff0c;但是速度很慢 在…

百度网盘的最新插件(懂得都懂)

下面先给大家介绍一下油猴插件。 这个插件为什么叫油猴&#xff1f; 现在我们经常提到的油猴插件&#xff0c;常指Tampermonkey&#xff0c;但Tampermonkey翻译过来是叫篡改猴&#xff0c;为什么会叫油猴呢&#xff1f;原因是因为另一个插件Greasemonkey&#xff0c;它翻译过…

求和:1-1/2+1/3-...1/n(JAVA)

所用知识&#xff1a; 1.输入输出语句 2.数据类型的自动转换 3.for循环控制语句 4.if条件控制语句 5.赋值语句 6.判断语句 import java.util.Scanner; class samp_5{public static void main(String[] args){Scanner snew Scanner(System.in);System.out.print("请输入数…

函数 1+1/2+1/3+…1/n

题目&#xff1a; 编写函数&#xff0c;求11/21/3…1/n。要求在主函数中输入n的值&#xff0c;并输出结果 代码&#xff1a; #include<stdio.h> #include<stdlib.h> int main() {int n;scanf("%d",&n);float num0;for(int i0;i<n;i){num1.0/(i…

《红楼梦》各版本总结

本文主要参考洪邑四维馆传人的 [文章][1] 对《红楼梦》的各版本和《红楼梦》脂评本作了图形化的展示。 受小博主所见所识限制&#xff0c;其中错误之处在所难免&#xff0c;恭请不吝赐教。 [1]&#xff1a;https://www.jianshu.com/p/474ea4f59081

《红楼梦》的作者真的是曹雪芹吗?

原文链接 随狂风去 ​ 尚书令 等 19,569 人赞同了该回答 作者名字确实是叫曹雪芹&#xff0c;但此曹雪芹绝不是江宁织造府的那位“曹雪芹”。 谈这个问题&#xff0c;必须先认识到一点&#xff1a;曹雪芹这三个字它只是个笔名&#xff0c;红楼的作者&#xff0c;在真实历史中&a…

引用还是传值——被打脸后才发现多年的理解是错的

这是一个很基础的问题&#xff0c;如果你已经理解透彻了&#xff0c;其实可以不需要往下看&#xff08;如果理解没错的话&#xff09;&#xff0c;因为相信你已经知道了答案&#xff0c;本篇主要是解释给和我一样一直以来有这样误解的人&#xff0c;事实上这是一个简单的问题&a…

一个页面同时请求多个接口,超过6个请求之后,stallled时间过长

Network Timing 使用Chrome浏览器请求多个接口时发现前面的请求Network Timing中stalled时间明显较短&#xff0c;到第四个请求时stalled时间开始加长&#xff0c;超过6个请求之后&#xff0c;stallled时间过长&#xff0c;导致接口整体请求时间变长&#xff0c;页面渲染变慢。…