Electron win10命令行调用与系统级别右键菜单项的实现

摘要:
=='darwin'){app.quit()})//在首次启动应用程序或正在运行的应用程序应用程序后,添加新的侦听器。在('activate')重新启动时,我们还可以通过process.argv(在Node.js中获取命令行参数的关键变量)在命令行打开Electron后获取命令行的参数。然后,我们可以通过在主进程准备阶段获取的process.argv参数来实现相应的功能。

我们在使用一些Electron开发的应用程序的时候,可以发现有些程序是可以通过命令行或者右键菜单唤起的。比如VSCodePicGo 那这个要怎么实现呢?

这里只实现win 平台,其他平台参考:

https://juejin.cn/post/6844903824709140488#heading-2

项目初始化

Electron 项目初始化很简单,这里不做赘述,请参考:

https://www.cnblogs.com/makalochen/p/14355788.html

参考里面的用的是 package 一般是用在调试,如果调试完了请用build,代码不用变

我们需要知道,electron-builder和electron-packager基本类似,不过builder打包完成的是安装包,而packager打包完成的是可执行文件,packager里面有项目源码,builder里面则是编译后的。这可能是两者的最大差别。

命令行调用

实现思路

首先我们要来实现命令行调用。其实Electron的命令行调用没有什么特殊的地方,与在Node.js端很类似,这里写个简单例子,你就明白了

创建main.js主进程脚本,内容如下

//为了管理应用程序的生命周期事件以及创建和控制浏览器窗口,您从 electron 包导入了 app 和 BrowserWindow 模块 。
const { app, BrowserWindow } = require('electron')

//在此之后,你定义了一个创建 新的浏览窗口的函数并将 nodeIntegration 设置为 true,将 index.html 文件加载到窗口中(第 12 行,稍后我们将讨论该文件)
function createWindow () {
    const win = new BrowserWindow({
         800,
        height: 600,
        webPreferences: {
            nodeIntegration: true
        }
    })

    win.loadFile('index.html')
}

//你通过调用 createWindow方法,在 electron app 第一次被初始化时创建了一个新的窗口。
app.whenReady().then(createWindow)

//您添加了一个新的侦听器,当应用程序不再有任何打开窗口时试图退出。 由于操作系统的 窗口管理行为 ,此监听器在 macOS 上是禁止操作的
app.on('window-all-closed', () => {
    if (process.platform !== 'darwin') {
        app.quit()
    }
})

//您添加一个新的侦听器,只有当应用程序激活后没有可见窗口时,才能创建新的浏览器窗口。 例如,在首次启动应用程序后或重启运行中的应用程序
app.on('activate', () => {
    if (BrowserWindow.getAllWindows().length === 0) {
        createWindow()
    }
})

//应用启动
app.on('ready', () => {
    /**
     *
     [
     'D:\myCode\my_electron\node_modules\electron\dist\electron.exe',
     '.'
     ] 111111111
     */
    console.log(process.argv, 111111111)
})

进入 ./out/my_electron-win32-x64目录 运行 my_electron.exe 并带上参数 aaa

.outmy_electron-win32-x64my_electron.exe aaa

效果

image-20210218104241702

关键出现了,我们可以通过process.argv这个在Node.js端获取命令行参数的关键变量同样获得Electron被命令行打开后的命令行参数。那么我们就可以在main进程的ready阶段通过获取的process.argv参数来实现我们对应的功能。

案例: 命令行调用传入文件路径并读取内容

定义命令格式

首先我们定义命令格式,这里要读取我就定义成这样 ,如:

程序 read 文件路径1 文件路径2

这样可以区分其他动作

定义主线程文件

上面的例子都是有窗口界面的,但是我们现在这个例子完全用不上窗口,所以可以将主线程文件内容改成如下内容

const { app } = require('electron')
const path = require('path');
const fs = require('fs-extra');
//应用启动
app.on('ready', () => {

    const getFiles = (argv = process.argv, cwd = process.cwd()) => {
        // 过滤['D:\myCode\my_electron\out\my_electron-win32-x64\my_electron.exe'', 'read']这两个参数,直接获取文件路径
        let files = argv.slice(2)
        //console.log(files, 'files .........');
        let result = []
        // 如果列表不为空
        if (files.length > 0) {
            result = files.map(item => {
                // 如果是绝对路径
                if (path.isAbsolute(item)) {
                    return {
                        path: item
                    }
                } else {
                    // 如果是相对路径,就拼接
                    let tempPath = path.join(cwd, item)

                    // 判断文件是否存在
                    if (fs.existsSync(tempPath)) {
                        return {
                            path: tempPath
                        }
                    } else {
                        return null
                    }
                }
            }).filter(item => item !== null) // 排除为null的路径
        }
        return result // 返回结果
    }
    //console.log(getFiles() , 33333);
    var files_path = getFiles();

    //遍历文件列表
    for(let i = 0; i < files_path.length; i++){
        let item  = files_path[i];
        //读取文件
        var data = fs.readFileSync(item.path, 'utf-8');
        console.log(data, 'file content....');
    }
})

安装扩展

npm install fs-extra

重新编译

npm run make

执行

.outmy_electron-win32-x64my_electron.exe read .outmy_electron-win32-x64version

效果

image-20210218115627592

系统级别右键菜单

如何实现?

Windows的右键菜单的原理其实很简单,在注册表里写入值就行。这里不会对Windows注册表的知识做过多的展开(自行百度)。我们只关注往哪里写值,写哪些值才能实现我们要的效果。

首先我们可以看看PicGo是如何实现右键菜单「Upload pictures w&ith PicGo」

image-20210218134847802

在系统里按快捷键WIN+R然后输入regedit打开注册表编辑器,我们来找到PicGo的右键菜单所在地:

HKEY_CLASSES_ROOT*shellPicGo

image-20210218135116131

可以看到一个「默认」的属性下的数据为「Upload pictures w&ith PicGo」,这个就是我们看到的菜单名。而一个叫「Icon」的属性下的数据为PicGoexe安装路径。所以可以认为这个Icon可以获取exeIcon并显示到菜单上。

不过这里还没有看到如何将文件路径作为参数传入PicGo的。继续看:

HKEY_CLASSES_ROOT*shellPicGocommand

image-20210218135452753

可以看出这个%1就是作为参数传给PicGo.exe的。有了PicGo作为参考,给自己的Electron应用实现一个系统级别的右键菜单也不难了。有人可能会说我可以在应用启动阶段通过某些npm包(比如windows-registry)来实现对注册表的写入。

通过electron-builder实现

实际上,在Windows平台,如果你是用electron-builder打包的话有一个更简洁的解决方案,那就是编写NSIS脚本来实现,对此electron-builder官方给出的文档可以一看。

本文不对NSIS脚本做过多的描述,你只需要知道它是用来生成Windows安装界面的一门脚本语言,你可以通过它来控制安装(卸载)界面都有哪些元素。并且它可以接入安装的生命周期,做一些操作,比如写入注册表。我们利用这个特性,来给程序做一个安装阶段写入注册表的操作,实现系统级别的右键菜单。

electron-builderNSIS暴露的钩子主要有customHeader, preInit, customInit, customInstall, customUnInstall,等等。

我们可以在customInstall阶段通过获取用户安装程序的路径$INSTDIR来实现对注册表关键值的写入。自己书写的installer.nsh默认放在项目的build目录下,那么electron-builder在构建Windows应用的时候将会自动读取这个文件以及package.json里的配置来生成安装界面。

写入注册表的格式大概是这样:

WriteRegStr <reg-path> <your-reg-path> <attr-name> <value>

以下是PicGoinstaller.nsh,参考:

!macro customInstall
WriteRegStr HKCR "*shellPicGo" "" "Upload pictures w&ith PicGo"
WriteRegStr HKCR "*shellPicGo" "Icon" "$INSTDIRPicGo.exe"
WriteRegStr HKCR "*shellPicGocommand" "" '"$INSTDIRPicGo.exe" "upload" "%1"'
!macroend
!macro customUninstall
DeleteRegKey HKCR "*shellPicGo"
!macroend

注意HKCR即是注册表目录HKEY_CLASSES_ROOT的缩写。在写value的时候如果要写多个参数,可以用单引号包起来。attr-name不写即为默认。相信有了PicGo的右键菜单注册表说明,你也能看得懂上面的PicGo的脚本了。同时注意我们应该在卸载阶段将之前写的注册表删除,以免用户卸载了应用之后菜单还在,上述脚本的后面部分是是在做这个事情。

因为上一章实现了命令行调用,所以我们的菜单就可以通过'"$INSTDIRPicGo.exe" "upload" "%1"'来实现菜单调用命令了。

参考自:

https://juejin.cn/post/6844903824709140488#heading-7

例:定义NSIS脚本安装时写入注册表和卸载删除注册表

添加文件build/installer.nsh

注意路径一定不能错,默认是这个路径,会自动读取配

;安装时写入
!macro customInstall
   WriteRegStr HKCR "*shellmy_electron" "" "测试........"
   WriteRegStr HKCR "*shellmy_electron" "Icon" "$INSTDIRmy_electron.exe"
   WriteRegStr HKCR "*shellmy_electroncommand" "" '"$INSTDIRmy_electron.exe" "read" "%1"'
!macroend
;卸载时清除
!macro customUninstall
   DeleteRegKey HKCR "*shellmy_electron"
!macroend

!macro customInstall 表示安装时触发,下面的三项都是注册表的值

!macro customUninstall表示卸载时触发

有关nsis 脚本的参考手册

https://omega.idv.tw/nsis/Contents.html

niss 脚本基础参考

https://www.cnblogs.com/jingmoxukong/p/5033622.html

image-20210218144600078

安装electron-builder

npm install electron-builder --save-dev

配置electron-builder

添加scripts脚本

参考:

https://www.cnblogs.com/yuNotes/p/12957018.html

https://www.e-learn.cn/topic/3904742

"build": "electron-builder"

image-20210218152214613

配置electron-builder配置项

参考:

https://www.electron.build/configuration/configuration

也可以不用配置,都有默认配置

常见配置参考

"build": {  // electron-builder配置
    "productName":"xxxx",//项目名 这也是生成的exe文件的前缀名
    "appId": "xxxxx",//包名  
    "copyright":"xxxx",//版权  信息
    "compression": "store", // "store" | "normal"| "maximum" 打包压缩情况(store 相对较快),store 39749kb, maximum 39186kb
    "directories": {
        "output": "build" // 输出文件夹
    }, 
    "asar": false, // asar打包
    "extraResources":  { // 拷贝dll等静态文件到指定位置
        "from": "./app-update.yml",
        "to": "./b.txt"
    },
    "win": {  
        "icon": "xxx/icon.ico"//图标路径,
        "extraResources":  { // 拷贝dll等静态文件到指定位置(用于某个系统配置)
            "from": "./app-update.yml",
            "to": "./b.txt"
        }
    },
    "nsis": {
        "oneClick": false, // 一键安装
        "guid": "xxxx", //注册表名字,不推荐修改
        "perMachine": true, // 是否开启安装时权限限制(此电脑或当前用户)
        "allowElevation": true, // 允许请求提升。 如果为false,则用户必须使用提升的权限重新启动安装程序。
        "allowToChangeInstallationDirectory": true, // 允许修改安装目录
        "installerIcon": "./build/icons/aaa.ico", // 安装图标
        "uninstallerIcon": "./build/icons/bbb.ico", //卸载图标
        "installerHeaderIcon": "./build/icons/aaa.ico", // 安装时头部图标
        "createDesktopShortcut": true, // 创建桌面图标
        "createStartMenuShortcut": true, // 创建开始菜单图标
        "shortcutName": "xxxx" // 图标名称
    }
  }
例:自定义niss安装配置
"nsis": {
      "shortcutName": "my_electron",
      "oneClick": false,
      "allowElevation": true,
      "allowToChangeInstallationDirectory": true,
      "perMachine": true,
      "include": "./build/installer.nsh"
    }

image-20210220152611474

执行打包

npm run build

image-20210218152923797

安装和卸载测试

安装,直接双击my_electron Setup 1.0.0.exe进行安装

image-20210218153153700

查看注册表

注意要F5刷新

image-20210220163127477

image-20210220163147743

卸载

image-20210220163621141

可以看到已经清除

免责声明:文章转载自《Electron win10命令行调用与系统级别右键菜单项的实现》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇MySQL分页时使用 limit+order by 会出现数据重复问题设置jdk版本下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

工具系列 | 如何搭建FTP服务,上传本地文件

需求 1、docker容器 2、文件服务器镜像:https://hub.docker.com/r/fauria/vsftpd 3、上传脚本:ThinkPHP5.1 4、上传依赖库:https://github.com/Nicolab/php-ftp-client 安装 FTP服务 docker run -d -v e:/ftp:/home/vsftpd -...

System.AccessViolationException,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。

从事件查看器中发现,IIS不定期崩溃并重启的现象。抓取crash dump文件后,发现能够看到异常,但没有堆栈信息(主要是只会看托管代码的堆栈,非托管的不清楚。),问题表现及dump日志的截图如下: 从dump文件的异常信息分析看,System.AccessViolationException,尝试读取或写入受保护的内存。这通常指示其他内存已损坏。...

C#调用java类、jar包方法。

一、将已经编译后的java中Class文件进行打包;打包命令JAR 如:将某目录下的所有class文件夹全部进行打包处理; 使用的命令:jar cvf test.jar -C com/ . 其中test.jar为要生成的jar包;com/ . 为指定的当前目录下的文件夹,该文件夹包括子文件夹及class文件; 二、到IKVM官方网站下载IKVM需要的组件 ...

js使用crypto实现md5WithRSA加密及验签

最近使用node对接一家支付三方,对方使用的是java 要求使用RSA加密 使用的算法是 md5WithRSA  encoding是utf8 输出是base64 在使用crypto-js和node-rsa无果后 查阅了node官方文档的crypto找到了答案  createSign方法传入加密算法创建一个sign对象,当然算法不是全部都支持的   使用...

Flask(Jinja2) 服务端模板注入漏洞vulhub

Flask(Jinja2) 服务端模板注入漏洞vulhub 前言 Flask简介 Flask 是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。 Flask 为你提供工具,库和技术来允许你构建一个 web 应用程序。这个 web 应用程序可以是一些 web 页面、博客、w...

ADO.NET- 中批量添加数据的几种实现方法比较

在.Net中经常会遇到批量添加数据,如将Excel中的数据导入数据库,直接在DataGridView控件中添加数据再保存到数据库等等。 方法一:一条一条循环添加 通常我们的第一反应是采用for或foreach循环一条一条的添加。这样的方法可想而知,效率肯定很低,可以慢到操作人员无法接受的那种。经过测试(局域网),1W条数据将会耗时3分42秒842毫秒 fo...