"use strict"; import { app, protocol, BrowserWindow, ipcMain, ipcRenderer, dialog, shell, Menu, webContents, } from "electron"; import { autoUpdater } from "electron-updater"; import { createProtocol } from "vue-cli-plugin-electron-builder/lib"; // import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer' import path from "path"; import child_process from "child_process"; import log from "electron-log"; import update from "./update"; import config from "./assets/js/config"; const { lang } = config; autoUpdater.logger = log; autoUpdater.logger.transports.file.level = "info"; let win = null; let loadingWin = null; // 调试自动升级 /** * checkForUpdatesAndNotify() just won't work in development mode. * * If you insist on test it in dev mode, you can do some hack with isPackaged: * * Be careful, do not use this hack for production * * Object.defineProperty(app, 'isPackaged', { get() { return true; } }); * * */ // Object.defineProperty(app, 'isPackaged', { // get() { // return true; // } // }); // 单例锁 const gotTheLock = app.requestSingleInstanceLock(); if (!gotTheLock) { app.quit(); } else { app.on("second-instance", (event, commandLine, workingDirectory) => { // 当运行第二个实例时,将会聚焦到myWindow这个窗口 if (win) { if (win.isMinimized()) win.restore(); win.focus(); if (commandLine[2]) { win.webContents.send( "selected-file", { filePaths: [commandLine[2]] }, "MenuList" ); } } }); } const remote = require("@electron/remote/main"); remote.initialize(); // remote.enable() const isDevelopment = process.env.NODE_ENV !== "production"; // const appUrl = 'http://localhost:8093/res/testParam/factorsAndThreshold'; const appUrl = "http://localhost:8093/res/testParam/callService?seconds=3"; const requestPromise = require("minimal-request-promise"); const checkService = function (cb) { requestPromise.get(appUrl).then( function (response) { log.info(response); log.info("Server started!"); cb(); }, function (response) { log.warn(response); log.info("Waiting for the server start..."); setTimeout(function () { checkService(cb); }, 500); } ); }; // const path = require('path'); // Scheme must be registered before the app is ready protocol.registerSchemesAsPrivileged([ { scheme: "app", privileges: { secure: true, standard: true, stream: true } }, ]); // TODO debug; // win.webContents.openDevTools() if (!isDevelopment) { Menu.setApplicationMenu(null); } // loading 窗口 const loadingURL = isDevelopment ? path.join(__dirname, "./loading.html") : `file://${__dirname}/loading.html`; const showLoading = (cb, argFn) => { loadingWin = new BrowserWindow({ // show: false, frame: false, width: 260, height: 260, resizable: false, transparent: true, webPreferences: { preload: path.join(__dirname, "./preload.js"), }, }); // loadingWin.once('show', () => { // cb(true); // }); // loadingWin.webContents.openDevTools(); loadingWin.loadURL(loadingURL); loadingWin.setSkipTaskbar(true); // loadingWin.show(); cb(true, argFn); // 启动java程序 // if (platform === 'win32') { // ipcMain.once('renderer-ready', (event, data) => { // let dir = path.resolve(__dirname, '..'); // serverProcess = require('child_process').execFile(dir + '/app_x64.exe'); // }); // } requestPromise.get(appUrl).then( function () { log.info("窗口初始化 服务正常"); // ipcRenderer.send('java-ready'); loadingWin.webContents.send("java-ready"); }, function () { log.info("窗口初始化 接口不通"); log.info("正在终止java进程,然后重启服务"); update(win.webContents, true); let stop = child_process.spawn("cmd.exe", ["/c", "stop.bat"]); stop.on("exit", function (code) { if (code > 0) { log.info('执行stop.bat没有正确exit, 错误码:' + code); return false; } log.info("java进程被终止,准备重启服务"); child_process.exec( `"${process.cwd()}\\ResMeterManager.exe" restart`, (err) => { if (err) { log.info("重启服务出错了stderr: " + JSON.stringify(err)); // 重新运行setup批处理 尝试重新注册服务 child_process.spawn("cmd.exe", ["/c", "setup_service.bat"]); log.info("服务异常 正在尝试重新注册服务"); } else { log.info("服务重启成功,连接中"); } // 等到服务就绪再重启 checkService(() => { loadingWin.webContents.send("java-ready"); }); } ); }); stop.on('error', (code, data) => { log.info('stop.bat 执行 error'); log.info(code); log.info(data); }); // // 重启服务 然后重启应用 // let restart = child_process.spawn('.\\ResMeterManager.exe', ['restart']); // restart.stdout.on('data', function (data) { // log.info('stdout: ' + data); // }); // restart.stderr.on('data', function (data) { // log.info('stderr: ' + data); // }); // restart.on('exit', (code) => { // if (code > 0) { // return false; // } // log.info('服务重启成功,连接中'); // // 等到服务就绪再重启 // checkService(() => { // loadingWin.webContents.send('java-ready'); // }); // }); } ); }; async function createWindow(wait, cb) { // Create the browser window. win = new BrowserWindow({ show: !wait, width: 1000, height: 600, webPreferences: { // Use pluginOptions.nodeIntegration, leave this alone // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info // nodeIntegration: process.env.ELECTRON_NODE_INTEGRATION, // contextIsolation: !process.env.ELECTRON_NODE_INTEGRATION nodeIntegration: false, webSecurity: true, allowEval: false, allowRunningInsecureContent: false, contextIsolation: true, enableRemoteModule: false, preload: path.join(__dirname, "preload.js"), }, }); // remote.enable(win.webContents); if (process.env.WEBPACK_DEV_SERVER_URL) { // Load the url of the dev server if in development mode await win.loadURL(process.env.WEBPACK_DEV_SERVER_URL); if (!process.env.IS_TEST) win.webContents.openDevTools(); } else { createProtocol("app"); // Load the index.html when not in development win.loadURL("app://./index.html"); } if (wait) { ipcMain.on("java-ready", () => { log.info("java-ready!"); loadingWin.hide(); loadingWin.close(); win.show(); }); } if (cb && "function" == typeof cb) { win.once("ready-to-show", () => { cb(win.webContents); }); } // 英文版不做升级 // 自动检测更新 软件的第一个实例打开后 为了不影响加载速度 在指定时间后做一次自检 win.once("ready-to-show", () => { log.info("ready event"); // TODO if ('US' != lang) { setTimeout(() => { update(win.webContents, true); }, 1000 * 30); } }); win.webContents.session.on("will-download", (e, item) => { // const filePath = path.join(saveUrl, item.getFilename()); // item.setSavePath(filePath); // 'C:\Users\kim\Downloads\第12次.zip' // let value; // //监听下载过程,计算并设置进度条进度 // item.on('updated', (evt, state) => { // if ('progressing' === state) { // //此处 用接收到的字节数和总字节数求一个比例 就是进度百分比 // if (item.getReceivedBytes() && item.getTotalBytes()) { // value = parseInt( // 100 * ( // item.getReceivedBytes() / item.getTotalBytes() // ) // ) // } // // 把百分比发给渲染进程进行展示 // // win.webContents.send('updateProgressing', value); // // mac 程序坞、windows 任务栏显示进度 // win.setProgressBar(value); // } // }); //监听下载结束事件 item.on("done", (e, state) => { //如果窗口还在的话,去掉进度条 // if (!win.isDestroyed()) { // win.setProgressBar(-1); // } //下载被取消或中断了 if (state === "interrupted") { dialog.showErrorBox( "下载失败", `文件 ${item.getFilename()} 因为某些原因被中断下载` ); } // 下载成功后打开文件所在文件夹 if (state === "completed") { setTimeout(() => { shell.showItemInFolder(item.getSavePath()); }, 1000); } }); }); } // Quit when all windows are closed. app.on("window-all-closed", () => { // On macOS it is common for applications and their menu bar // to stay active until the user quits explicitly with Cmd + Q if (process.platform !== "darwin") { app.quit(); } }); app.on("activate", () => { log.info("app activate event"); // On macOS it's common to re-create a window in the app when the // dock icon is clicked and there are no other windows open. if (BrowserWindow.getAllWindows().length === 0) createWindow(); }); // This method will be called when Electron has finished // initialization and is ready to create browser windows. // Some APIs can only be used after this event occurs. app.on("ready", async () => { log.info("app ready event"); let cb = undefined; if (process.argv[1]) { cb = (sender) => { log.info("call selected-file.." + process.argv[1]); sender.send( "selected-file", { filePaths: [process.argv[1]] }, "MenuList" ); }; } if (isDevelopment) { createWindow(); } else { showLoading(createWindow, cb); } }); // 所有的新开窗口事件都调用系统默认浏览器来打开页面 app.on("web-contents-created", (e, webContents) => { webContents.on("new-window", (event, url) => { event.preventDefault(); shell.openExternal(url); }); }); ipcMain.on("open-file-dialog", (event, data) => { dialog .showOpenDialog({ filters: [{ name: "xml", extensions: ["xml"] }], properties: ["openFile"], }) .then((files) => { // console.log(files, '0000000') if (files) { event.sender.send("selected-file", files, data); } }); }); ipcMain.on("open-directory-dialog", (event, data) => { dialog .showOpenDialog({ properties: ["openDirectory"], }) .then((files) => { if (files) { event.sender.send("selected-directory", files, data); } }); }); ipcMain.on("check-update", (event) => { // checkForUpdates(); update(event.sender); }); ipcMain.on("download-update", () => { autoUpdater.downloadUpdate(); }); ipcMain.on("quitAndInstall", () => { autoUpdater.quitAndInstall(); }); ipcMain.on("db-export", () => { // 打开窗口选择导出文件的路径 let path = dialog.showSaveDialogSync({ title: "导出数据库", filters: [{ name: "db", extensions: ["db"] }], }); if (!path) { return false; } let src = "res.db"; child_process.exec( `copy "${process.cwd()}\\${src}" "${path}" /Y /V`, (err) => { if (err) { log.info("数据库导出出错了stderr: " + JSON.stringify(err)); return; } log.info("数据库导出成功"); // 打开文件夹 shell.showItemInFolder(path); } ); }); ipcMain.on("db-import", () => { let stop = child_process.spawn("cmd.exe", ["/c", "stop.bat"]); stop.on("exit", function (code) { if (code > 0) { return false; } // 关闭服务成功后 打开选择文件对话框 让用户选择db文件 然后复制 let path = dialog.showOpenDialogSync({ filters: [{ name: "db", extensions: ["db"] }], properties: ["openFile"], }); if (path) { // 然后复制文件 let src = "res.db"; // 然后复制文件 child_process.exec( `copy "${path}" "${process.cwd()}\\${src}" /Y /V`, (err) => { if (err) { log.info("数据库导入出错了stderr: " + JSON.stringify(err)); return; } log.info("数据库导入成功"); // 打开服务 let restart = child_process.spawn("ResMeterManager.exe", ["restart"]); log.info("restart"); restart.stdout.on("data", function (data) { log.info("stdout: " + data); }); restart.stderr.on("data", function (data) { log.info("stderr: " + data); }); restart.on("exit", (code) => { if (code > 0) { return false; } log.info("服务重启成功,准备重启应用"); // 等到服务就绪再重启 checkService(() => { // 重新启动软件 app.relaunch(); app.exit(); }); }); let status = child_process.spawn("ResMeterManager.exe", ["status"]); log.info("restart"); status.stdout.on("data", function (data) { log.info("stdout: " + data); }); status.stderr.on("data", function (data) { log.info("stderr: " + data); }); } ); } else { // 重启服务 然后重启应用 let restart = child_process.spawn("ResMeterManager.exe", ["restart"]); log.info("restart"); restart.stdout.on("data", function (data) { log.info("stdout: " + data); }); restart.stderr.on("data", function (data) { log.info("stderr: " + data); }); restart.on("exit", (code) => { if (code > 0) { return false; } log.info("服务重启成功,准备重启应用"); // 等到服务就绪再重启 checkService(() => { // 重新启动软件 app.relaunch(); app.exit(); }); }); } }); }); // Exit cleanly on request from parent process in development mode. if (isDevelopment) { if (process.platform === "win32") { process.on("message", (data) => { if (data === "graceful-exit") { app.quit(); } }); } else { process.on("SIGTERM", () => { app.quit(); }); } }