摘要:當(dāng)設(shè)置了參數(shù)時(shí),將作為命令行參數(shù)傳遞。托盤關(guān)閉向和微信一樣,有的時(shí)候我們并不想讓用戶通過點(diǎn)關(guān)閉按鈕的時(shí)候就關(guān)閉程序,而是把程序最小化到托盤,在托盤上做真正的退出操作。首先要監(jiān)聽窗口的關(guān)閉事件,阻止用戶關(guān)閉操作的默認(rèn)行為。
在某種情況下,我們可能希望我們的客戶端程序盡可能連續(xù)不斷的運(yùn)行在我們的系統(tǒng)中,并保持穩(wěn)定。
以下幾種方式可以幫助我們做到這一點(diǎn):
1.崩潰監(jiān)控electron為我們提供了監(jiān)聽程序崩潰的事件:
Event: "crashed" 返回: event Event killed Boolean 當(dāng)渲染進(jìn)程崩潰或被結(jié)束時(shí)觸發(fā)
此事件是用來家庭渲染進(jìn)程崩潰的,但是當(dāng)主進(jìn)程意外崩潰時(shí)也會(huì)觸發(fā)該事件。
在監(jiān)測到程序崩潰后,我們要讓程序重新啟動(dòng),此時(shí)我們要首先判斷window對象是否被銷毀,也就是主進(jìn)程是否被殺死,還是渲染進(jìn)程崩潰,同時(shí)作出不同的處理。
當(dāng)mainWin被銷毀時(shí)我們直接重啟整個(gè)應(yīng)用,使用如下api:
app.relaunch([options]) options Object (可選) args String execPath String (可選) 從當(dāng)前實(shí)例退出,重啟應(yīng)用。 默認(rèn)情況下,新的實(shí)例會(huì)和當(dāng)前實(shí)例使用相同的工作目錄以及命令行參數(shù)。 當(dāng)設(shè)置了 args 參數(shù)時(shí), args 將作為命令行參數(shù)傳遞。 當(dāng)設(shè)置了 execPath ,execPath 將被執(zhí)行以重新啟動(dòng),而不是當(dāng)前的應(yīng)用程序。 請注意, 此方法在執(zhí)行時(shí)不會(huì)退出當(dāng)前的應(yīng)用程序, 你需要在調(diào)用 app.relaunch 方法后再執(zhí)行 app. quit 或者 app.exit 來讓應(yīng)用重啟。
只是渲染進(jìn)程崩潰,我們只需將其他窗體銷毀,然后重新load我們的主窗口。
崩潰重啟邏輯:
if (mainWin.isDestroyed()) { app.relaunch(); app.exit(0); } else { BrowserWindow.getAllWindows().forEach((w) => { if (w.id !== mainWin.id) w.destroy(); }); mainWin.reload(); }
當(dāng)然,我們還要記錄一下程序的崩潰日志,我們要確保日志接口發(fā)出成功后再重啟我們的程序:
下面是程序崩潰后的完整邏輯:
import { BrowserWindow, app, dialog} from "electron"; const mainWindow = BrowserWindow.fromId(global.mainId); mainWindow.webContents.on("crashed", () => { const options = { type: "error", title: "進(jìn)程崩潰了", message: "這個(gè)進(jìn)程已經(jīng)崩潰.", buttons: ["重載", "退出"], }; recordCrash().then(() => { dialog.showMessageBox(options, (index) => { if (index === 0) reloadWindow(mainWindow); else app.quit(); }); }).catch((e) => { console.log("err", e); }); }) function recordCrash() { return new Promise(resolve => { // 崩潰日志請求成功.... resolve(); }) } function reloadWindow(mainWin) { if (mainWin.isDestroyed()) { app.relaunch(); app.exit(0); } else { BrowserWindow.getAllWindows().forEach((w) => { if (w.id !== mainWin.id) w.destroy(); }); mainWin.reload(); } }
寫好代碼之后,我們可以直接在控制臺(tái)輸入 process.crash()來進(jìn)行測試,或者直接在任務(wù)管理器殺掉我們的進(jìn)程進(jìn)行測試。
2.開機(jī)自啟開機(jī)自啟是保證我們的程序能長時(shí)間在機(jī)器上運(yùn)行很重要的一點(diǎn)。
電腦上有很多程序都設(shè)置了開機(jī)自啟動(dòng),比如qq,微信,迅雷等,他們都是通過修改注冊表來實(shí)現(xiàn)的,我們可以看一下注冊表 SoftwareMicrosoftWindowsCurrentVersionRun:
所以我們也要將我們程序的路徑寫到這里。
發(fā)現(xiàn)了一個(gè)非常好的寫注冊表的模塊,winreg
注意mac不能使用這個(gè)模塊,所以首先要判斷是否為window再引用這個(gè)模塊。
借助這個(gè)模塊我們可以非常簡單的修改注冊表:
const WinReg = require("winreg"); const startOnBoot = { enableAutoStart: function (name, file, callback) { var key = getKey(); key.set(name, WinReg.REG_SZ, file, callback || noop); }, disableAutoStart: function (name, callback) { var key = getKey(); key.remove(name, callback || noop); }, getAutoStartValue: function (name, callback) { var key = getKey(); key.get(name, function (error, result) { if (result) { callback(result.value); } else { callback(null, error); } }); } }; function noop() { } const RUN_LOCATION = "SoftwareMicrosoftWindowsCurrentVersionRun"; function getKey() { return new WinReg({ hive: WinReg.HKCU, //CurrentUser, key: RUN_LOCATION }); } export default function autoStart() { startOnBoot.getAutoStartValue("MY_CLIENT_AUTOSTART", function (value) { if (!value) { startOnBoot.enableAutoStart("MY_CLIENT_AUTOSTART", process.execPath, function () { console.log("開機(jī)自動(dòng)啟設(shè)置"); }); } }); }
執(zhí)行完程序之后,再看注冊表,發(fā)現(xiàn)我們程序的路徑已經(jīng)寫進(jìn)去了:
然后電腦重啟后你的程序就自動(dòng)啟動(dòng)了。
3.托盤關(guān)閉向qq和微信一樣,有的時(shí)候我們并不想讓用戶通過點(diǎn)關(guān)閉按鈕的時(shí)候就關(guān)閉程序,而是把程序最小化到托盤,在托盤上做真正的退出操作。
首先要監(jiān)聽窗口的關(guān)閉事件,阻止用戶關(guān)閉操作的默認(rèn)行為。
mainWindow.on("close", (event) => { mainWindow.hide(); event.preventDefault(); });
然而這時(shí)你發(fā)現(xiàn),這只是最小化了程序,任務(wù)欄里程序依然存在,我們需要讓程序在任務(wù)欄里也消失:
mainWindow.on("close", (event) => { mainWindow.hide(); mainWindow.setSkipTaskbar(true); event.preventDefault(); });
這時(shí)程序就再也找不到了,任務(wù)托盤中也沒有我們的程序,所以我們要先創(chuàng)建好任務(wù)托盤,并做好事件監(jiān)聽:
function createTray() { const mainWindow = BrowserWindow.fromId(global.mainId); tray = new Tray(path.join(global.__dirname, "icon.ico")); const contextMenu = Menu.buildFromTemplate([ { label: "退出", click: () => { mainWindow.destroy(); app.quit(); } }, ]) tray.setToolTip("我的客戶端") tray.setContextMenu(contextMenu) tray.on("click", () => { if (mainWindow.isVisible()) { mainWindow.hide(); mainWindow.setSkipTaskbar(false); } else { mainWindow.show(); mainWindow.setSkipTaskbar(true); } }) }
以上這些操作為我們的程序又增加了好幾層的防護(hù)措施,我們的程序就不會(huì)那么輕而易舉的掛掉啦!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99066.html
摘要:調(diào)試集成環(huán)境選擇模塊,簡單分離開發(fā),測試,線上環(huán)境。程序保護(hù)開機(jī)自啟托盤最小化崩潰監(jiān)控升級一行代碼接入升級平臺(tái),實(shí)現(xiàn)客戶端升級功能打包構(gòu)建一個(gè)指令搞定打包項(xiàng)目地址 項(xiàng)目地址 : https://github.com/ConardLi/electron-react electron-react electron + react + react-router + mobx + webpac...
摘要:實(shí)現(xiàn)原理通過修改注冊表來實(shí)現(xiàn)開機(jī)自啟和通過鏈接調(diào)起應(yīng)用類似百度網(wǎng)盤點(diǎn)擊連接打開應(yīng)用程序使用到的插件使用說明將下方例子中的替換為自己的應(yīng)用別名可以不為名稱開機(jī)自啟開機(jī)自啟動(dòng)查看開機(jī)自啟注冊表是否已經(jīng)注冊未注冊或注冊地址與現(xiàn)地址不一致則進(jìn)行注 實(shí)現(xiàn)原理 通過修改注冊表來實(shí)現(xiàn)開機(jī)自啟和通過鏈接調(diào)起應(yīng)用(類似百度網(wǎng)盤點(diǎn)擊連接打開應(yīng)用程序) 使用到的插件 node-regedit yarn ...
摘要:使用將應(yīng)用程序放入托盤此系列文章的應(yīng)用示例已發(fā)布于可以或下載后運(yùn)行查看歡迎使用模塊允許您在操作系統(tǒng)的通知區(qū)域中創(chuàng)建圖標(biāo)此圖標(biāo)還可以附加上下文菜單在瀏覽器中查看完整文檔托盤支持進(jìn)程示例按鈕使用模塊向主進(jìn)程發(fā)送消息在主進(jìn)程中應(yīng)用程序會(huì)被告 使用 Electron 將應(yīng)用程序放入托盤 此系列文章的應(yīng)用示例已發(fā)布于 GitHub: electron-api-demos-Zh_CN. 可以 Cl...
摘要:下面就來分享提高云中服務(wù)器的安全等級的個(gè)措施,讓企業(yè)有針對性的進(jìn)行安全防護(hù)。對服務(wù)器安全而言,安裝防火墻非常必要。防火墻對于非法訪問具有很好的預(yù)防作用,但是安裝了防火墻并不等于服務(wù)器安全了。 近年以來,云計(jì)算已成為信息安全界的寵兒,各家企業(yè)前仆后繼的躋身于云行列中去。 云技術(shù)的出現(xiàn),確實(shí)帶給了現(xiàn)代企業(yè)非常大的便利,但與好處伴隨而來的,也有不能回避的信息安全隱患。 下面就來分享提高云中服...
閱讀 3558·2021-11-08 13:15
閱讀 2115·2019-08-30 14:20
閱讀 1396·2019-08-28 18:08
閱讀 989·2019-08-28 17:51
閱讀 1496·2019-08-26 18:26
閱讀 2998·2019-08-26 13:56
閱讀 1494·2019-08-26 11:46
閱讀 2594·2019-08-23 14:22