zoukankan      html  css  js  c++  java
  • 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_MACHINESOFTWAREClasses,包含了所有应用程序运行时必需的信息:

    在文件和应用程序之间所有的扩展名和关联; 
    所有的驱动程序名称;   类的ID数字(所要存取项的名字用数字来代替);
      用于应用程序和文件的图标;
      在注册表中HKEY_CLASSES_ROOT是系统中控制所有数据文件的项。这个在Win95和Winnt中是相通的。HKEY_CLASSES_ROOT控制键包括了所有文件扩展和所有和执行文件相关的文件。它同样也决定了当一个文件被双击时起反应的相关应用程序。
    右键菜单的开启

    HKEY_CLASSES_ROOT*shell密存加密command意思是打开cmd
    @=""D:\application\secretsave\secretsave.exe" "%1"1"这句话是cmd里面的命令,应用路径,最后面的1是参数
    将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:applicationsecretsavesecretsave.exe", "D:workelectronAesTest.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" "" '"$INSTDIRsecretsave.exe" "%1" "1"'
      WriteRegStr HKCR "*shell密存解密command" "" '"$INSTDIRsecretsave.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 构建打包总结

    Electron 渲染进程之间的通信

     

     

       

  • 相关阅读:
    转:一个实例明白AutoResetEvent和 ManulResetEvent的用法
    取消office2010默认微软拼音输入法
    错误:在 ServiceModel 客户端配置部分中,找不到引用协定“*********.I******”的默认终结点元素。这可能是因为未找到应用程序的配置文件,或者是因为客户端元素中找不到与此协定匹配的终结点元素。
    ASP 空字符串、IsNull、IsEmpty区别分析
    asp.net防止多次登录的方法
    关于javascript的keycode
    学习资料
    关于javascript中的typeof和instanceof介绍
    完整的SQLHelper
    图片自动分割代码求注释
  • 原文地址:https://www.cnblogs.com/phoebeyue/p/12927193.html
Copyright © 2011-2022 走看看