electron-vue项目修改注册表在系统右键菜单中添加功能
一、使用reg文件测试
reg文件内容:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\*\shell\密存加密\command]
@="\"D:\\application\\secretsave\\secretsave.exe\" \"%1\"\1"
[HKEY_CLASSES_ROOT\*\shell\密存解密\command]
@="\"D:\\application\\secretsave\\secretsave.exe\" \"%1\"\2"
HKEY_CLASSES_ROOT其实就是HKEY_LOCAL_MACHINE\SOFTWARE\Classes,包含了所有应用程序运行时必需的信息:
在文件和应用程序之间所有的扩展名和关联;
所有的驱动程序名称; 类的ID数字(所要存取项的名字用数字来代替);
用于应用程序和文件的图标;
在注册表中HKEY_CLASSES_ROOT是系统中控制所有数据文件的项。这个在Win95和Winnt中是相通的。HKEY_CLASSES_ROOT控制键包括了所有文件扩展和所有和执行文件相关的文件。它同样也决定了当一个文件被双击时起反应的相关应用程序。
右键菜单的开启
HKEY_CLASSES_ROOT\*\shell\密存加密\command意思是打开cmd
@=
"\"D:\\application\\secretsave\\secretsave.exe\" \"%1\"\1"
这句话是cmd里面的命令,应用路径,最后面的1是参数<br>将req文件放在安装好的应用根目录下,右键编辑注册表,修改成功
二、对参数处理
在主进程main/index.js里面
app.on('ready', function () {
createWindow()
global.sharedObject = {prop1: process.argv}
})
在render的vue文件里接收
mounted () {
let args = remote.getGlobal('sharedObject').prop1
console.log(args)
let types = ['1','2']
if (args.length >= 3 && types.includes(args[2])) {
args[1] = args[1].replace(/\\/g, '/')
this.getArgFile(args)
}
}
右键点击文件唤起应用时args打印结果
["D:\application\secretsave\secretsave.exe", "D:\work\electron\AesTest.rar", "1"]
数组第二个值是文件路径,第三个值是注册表传递过来的参数
三、使用electron-builder里面的nsis对象,让应用在安装时写入注册表
1、package.json里面配置:
"nsis": {
"oneClick": false,
"perMachine": true,
"allowElevation": true,
"allowToChangeInstallationDirectory": true,
"createDesktopShortcut": true,
"runAfterFinish": true,
"shortcutName": "无忧密存",
"installerIcon": "./static/icon.ico",
"uninstallerIcon": "./static/icon.ico",
"include": "installer.nsh"
},
- include 指定要包含 nsis 的脚本,基于内置的nsis脚本进一步扩展,这个对于构建需求严格得安装过程相当有用
- script 指定自定义使用 nsis 的脚本,完全自己控制nsis 的打包,用于自定义安装程序,默认为build / installer.nsi
关于include
和 script
到底选择哪一个 ?
在对个性化安装过程需求并不复杂,只是需要修改一下安装位置,卸载提示等等的简单操作建议使用include
配置,如果你需要炫酷的安装过程,建议使用script
进行完全自定义。
我们只是添加两个按钮,使用include就好
2、编写installer.nsh文件,放在build文件夹下
!macro customInstall
WriteRegStr HKCR "CenDC" "URL Protocol" ""
WriteRegStr HKCR "CenDC" "" "URL:CenDC Protocol Handler"
WriteRegStr HKCR "*\shell\密存加密\command" "" '"$INSTDIR\secretsave.exe" "%1" "1"'
WriteRegStr HKCR "*\shell\密存解密\command" "" '"$INSTDIR\secretsave.exe" "%1" "2"'
!macroend
!macro customUninstall
DeleteRegKey HKCR "*\shell\密存加密"
DeleteRegKey HKCR "*\shell\密存解密"
!macroend
简单解释脚本的含义,具体了解详情请看下方参考资料:
!macro 是定义宏
customInstall会在文件安装后自动调用(electron-builder实现)
WriteRegStr 是写注册表 如果原来有会覆盖。
$INSTDIR 是所选的文件安装路径
HKCR
即是注册表目录HKEY_CLASSES_ROOT
的缩写。在写value
的时候如果要写多个参数,可以用单引号包起来。attr-name
不写即为默认
customUnInstall在卸载阶段将之前写的注册表删除,以免用户卸载了应用之后菜单还在
四、问题修改
效果虽然达到了,但是每次右键都会新开一个应用,node服务端口就会占用
1、解决端口占用问题,实现单例应用的命令行调用:如果应用已经打开的情况下,不打开新窗口
Electron版本v4.x以上用的是app.
requestSingleInstanceLock,2.0用的是app.makeSingleInstance
const { app } = require('electron')
let mainWindow = null
const gotTheLock = app.requestSingleInstanceLock() // 拿到单例锁
if (!gotTheLock) { // 如果一个应用二次打开,那么getTheLock为false
app.quit() // 立即退出二次打开的应用
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => { // 一个应用尝试打开第二个实例时触发
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
}
})
// Create myWindow, load the rest of the app, etc...
app.on('ready', () => {
})
}
端口占用的问题解决了,但是数据无法传递,应用只是聚焦,并没有做任何处理
2、进程通信修改
global.sharedObject可以做到数据共享,却没有实质的通信功能;
ipcMain与
ipcRenderer需要渲染进程先发消息,于是选择了主进程用
webContents.send发送消息,渲染进程用ipcRenderer监听
修改后代码如下:
if (!gotTheLock) {
app.quit()
} else {
app.on('second-instance', (event, commandLine, workingDirectory) => {
// 当运行第二个实例时,将会聚焦到myWindow这个窗口
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
global.sharedObject = {prop1: process.argv}
mainWindow.webContents.send('getRightPath', process.argv)
/* dialog.showMessageBox({
title: 'second',
message: 'second:' + commandLine + ' workingDirectory' + workingDirectory
}) */
} else {
if (app.isReady()) createWindow()
global.sharedObject = {prop1: process.argv}
}
})
// mac环境
app.on('open-url', (event, commandLine, workingDirectory) => {
// 当运行第二个实例时,将会聚焦到myWindow这个窗口
if (mainWindow) {
if (mainWindow.isMinimized()) mainWindow.restore()
mainWindow.focus()
global.sharedObject = {prop1: process.argv}
mainWindow.webContents.send('getRightPath', process.argv)
} else {
if (app.isReady()) createWindow()
global.sharedObject = {prop1: process.argv}
}
})
// 创建 myWindow, 加载应用的其余部分, etc...
app.on('ready', () => {
createWindow()
global.sharedObject = {prop1: process.argv}
})
}
渲染进程vue组件里面改为:
const ipc = require('electron').ipcRenderer
methods: {
dealArgs () {
let args = remote.getGlobal('sharedObject').prop1
// console.log("666--:",args)
let types = ['1','2']
if (args.length >= 3 && types.includes(args[2])) {
args[1] = args[1].replace(/\\/g, '/')
this.getArgFile(args)
}
}
},
mounted () {
let _this = this
this.dealArgs() // 第一次进入时也处理
ipc.on('getRightPath', function (event, argv) {
_this.dealArgs()
})
}
参考资料:
Electron-vue开发实战7——命令行调用与系统级别右键菜单项的实现
electron-builder构建的安装包,安装时通过nsis脚本自动导入注册表
Electron 渲染进程之间的通信
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
2018-05-31 css3新单位vw、vh、vmin、vmax的使用介绍
2018-05-31 vue中的css作用域、vue中的scoped坑点
2018-05-31 vue组件中的样式属性:scoped,解决在父组件中无法修改子组件样式问题
2018-05-31 浅析vue cli4的webpack配置属性 devServer 详解 和 devServer.proxy 工作原理解析
2018-05-31 浅析type和interface的异同点