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 構建打包總結

Electron 渲染進程之間的通信

 


免責聲明!

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



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