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是參數
將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 構建打包總結

Electron 渲染進程之間的通信

 

 

 

 

   


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM