From d761a691a0251da0f62afa58470eabb960464d5c Mon Sep 17 00:00:00 2001 From: Samuel-luo <1319433916@qq.com> Date: Wed, 4 Jan 2023 12:35:07 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96=E6=B5=8F=E8=A7=88=E5=99=A8?= =?UTF-8?q?=E8=BF=9B=E7=A8=8B=E6=97=A0=E6=B3=95=E6=89=93=E5=BC=80=E9=97=AE?= =?UTF-8?q?=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- forge.config.js | 2 +- main.js | 60 +++++++++++++++++++++++++++++++--------------- package-lock.json | 29 +++++++--------------- package.json | 1 + updater.cpp | 1 + updater.exe | Bin 1013871 -> 1013871 bytes 6 files changed, 52 insertions(+), 41 deletions(-) diff --git a/forge.config.js b/forge.config.js index d8ff3ea..48ce300 100644 --- a/forge.config.js +++ b/forge.config.js @@ -1,7 +1,7 @@ module.exports = { packagerConfig: { asar: true, - ignore: /updater\.cpp/, + ignore: /(updater\.cpp|forge\.config\.js|\.gitignore)/, }, rebuildConfig: {}, makers: [ diff --git a/main.js b/main.js index 8093c68..a8694e6 100644 --- a/main.js +++ b/main.js @@ -1,12 +1,13 @@ const {app, BrowserWindow, ipcMain} = require('electron'); -const {fork} = require('child_process'); +const {spawn, fork, exec} = require('child_process'); const path = require("path"); const fs = require("fs"); const axios = require("axios"); -const {spawn} = require('child_process'); +const asar = require('asar'); let subprocesses = []; let isLoading = false; +const resourcePath = path.parse(app.getAppPath()).dir; let logFn = (...args) => { console.log(...args); } @@ -27,6 +28,7 @@ const createWindow = () => { } app.whenReady().then(() => { + if (app.isPackaged && !fs.existsSync(`${resourcePath}/release`)) asar.extractAll(`${resourcePath}/app.asar`, `${resourcePath}/release`); ipcMain.handle('start', handleStart) ipcMain.handle('updateApp', updateApp) ipcMain.handle('get-rec-info', getRecInfo) @@ -44,12 +46,10 @@ app.on('window-all-closed', () => { }) app.on('before-quit', () => { - const resourcePath = path.parse(app.getAppPath()).dir; if (isLoading) _removeFile(`${resourcePath}/app.asar-new`); }) app.on('quit', () => { - const resourcePath = path.parse(app.getAppPath()).dir; if (fs.existsSync(`${resourcePath}/updater.exe`) && fs.existsSync(`${resourcePath}/app.asar-new`)) { logFn("开始替换资源..."); const child = spawn(`"${resourcePath}/updater.exe"`, { @@ -80,16 +80,25 @@ async function handleStart(e, account, password, platform, isFillAP, chromeUrl) return 1; } +function getRecInfo() { + try { + return fs.readFileSync(app.isPackaged ? app.getAppPath() + '/data.rec' : './data.rec', {encoding: 'utf8'}); + } catch (err) { + return "{}"; + } +} + async function updateApp() { if (!app.isPackaged || isLoading) return; + _closeChildProcess(); logFn("开始更新..."); - const resourcePath = path.parse(app.getAppPath()).dir; try { logFn("创建更新脚本..."); - if (!fs.existsSync(`${resourcePath}/updater.exe`)) fs.copyFileSync(app.getAppPath() + '/updater.exe', `${resourcePath}/updater.exe`); + if (!fs.existsSync(`${resourcePath}/updater.exe`)) _copyFile(app.getAppPath() + '/updater.exe', `${resourcePath}/updater.exe`); logFn("开始下载最新版本资源..."); isLoading = true; if (await _downloadFile('https://github.com/Samuel-luo/network_class_Ganker/releases/latest/download/app.asar', `${resourcePath}/app.asar-new`).then(() => 1).catch(() => 0)) { + _removeDir(`${resourcePath}/release`); app.exit(0) } else { logFn("下载失败!"); @@ -101,17 +110,9 @@ async function updateApp() { } } -function getRecInfo() { - try { - return fs.readFileSync(app.isPackaged ? app.getAppPath() + '/data.rec' : './data.rec', {encoding: 'utf8'}); - } catch (err) { - return "{}"; - } -} - function createChildProcess(data, index) { - let subprocess = fork(app.isPackaged ? app.getAppPath() + '/index.js' : './index.js', { - cwd: app.isPackaged ? app.getAppPath() : __dirname, stdio: ['pipe', 'pipe', 'pipe', 'ipc'], env: { + let subprocess = fork(app.isPackaged ? path.join(resourcePath, 'release', 'index.js') : './index.js', { + cwd: app.isPackaged ? `${resourcePath}/release` : __dirname, stdio: ['pipe', 'pipe', 'pipe', 'ipc'], env: { account: data.account, password: data.password, platform: data.platform, isFillAP: data.isFillAP, chromeUrl: data.chromeUrl } }); @@ -142,9 +143,7 @@ function _closeChildProcess() { let subprocess; while (subprocess = subprocesses.shift()) { try { - if (subprocess) { - subprocess.send('exit'); - } + subprocess.send('exit'); } catch (err) { // 静默处理 err } @@ -161,8 +160,31 @@ async function _downloadFile(url, filepath) { fs.writeFileSync(filepath, response.data, {encoding: "binary"}) } +function _copyFile(from, to) { + fs.copyFileSync(from, to); +} + function _removeFile(filePath) { while (fs.existsSync(filePath)) { fs.rmSync(filePath); } } + +function _removeDir(filePath) { + const files = [] + if (fs.existsSync(filePath)) { + const files = fs.readdirSync(filePath) + files.forEach((file) => { + const nextFilePath = `${filePath}/${file}` + const states = fs.statSync(nextFilePath) + if (states.isDirectory()) { + // recurse + _removeDir(nextFilePath) + } else { + // delete file + fs.unlinkSync(nextFilePath) + } + }) + fs.rmdirSync(filePath) + } +} diff --git a/package-lock.json b/package-lock.json index ee9fe55..54a2f03 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,14 +1,15 @@ { "name": "network_class", - "version": "0.1.0", + "version": "0.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "network_class", - "version": "0.1.0", + "version": "0.2.0", "license": "MIT", "dependencies": { + "asar": "^3.2.0", "axios": "^1.2.2", "electron-squirrel-startup": "^1.0.0", "selenium-webdriver": "^4.5.0" @@ -1716,7 +1717,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, "optional": true, "dependencies": { "@types/minimatch": "*", @@ -1743,14 +1743,13 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true, "optional": true }, "node_modules/@types/node": { "version": "16.18.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true + "devOptional": true }, "node_modules/@types/responselike": { "version": "1.0.0", @@ -1905,8 +1904,6 @@ "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", "deprecated": "Please use @electron/asar moving forward. There is no API change, just a package name change", - "dev": true, - "optional": true, "dependencies": { "chromium-pickle-js": "^0.2.0", "commander": "^5.0.0", @@ -1927,8 +1924,6 @@ "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "optional": true, "engines": { "node": ">= 6" } @@ -2265,8 +2260,7 @@ "node_modules/chromium-pickle-js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", - "dev": true + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==" }, "node_modules/clean-stack": { "version": "2.2.0", @@ -8395,7 +8389,6 @@ "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", - "dev": true, "optional": true, "requires": { "@types/minimatch": "*", @@ -8421,14 +8414,13 @@ "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", - "dev": true, "optional": true }, "@types/node": { "version": "16.18.3", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.3.tgz", "integrity": "sha512-jh6m0QUhIRcZpNv7Z/rpN+ZWXOicUUQbSoWks7Htkbb9IjFQj4kzcX/xFCkjstCj5flMsN8FiSvt+q+Tcs4Llg==", - "dev": true + "devOptional": true }, "@types/responselike": { "version": "1.0.0", @@ -8550,8 +8542,6 @@ "version": "3.2.0", "resolved": "https://registry.npmjs.org/asar/-/asar-3.2.0.tgz", "integrity": "sha512-COdw2ZQvKdFGFxXwX3oYh2/sOsJWJegrdJCGxnN4MZ7IULgRBp9P6665aqj9z1v9VwP4oP1hRBojRDQ//IGgAg==", - "dev": true, - "optional": true, "requires": { "@types/glob": "^7.1.1", "chromium-pickle-js": "^0.2.0", @@ -8563,9 +8553,7 @@ "commander": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/commander/-/commander-5.1.0.tgz", - "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==", - "dev": true, - "optional": true + "integrity": "sha512-P0CysNDQ7rtVw4QIQtm+MRxV66vKFSvlsQvGYXZWR3qFU0jlMKHZZZgw8e+8DSah4UDKMqnknRDQz+xuQXQ/Zg==" } } }, @@ -8822,8 +8810,7 @@ "chromium-pickle-js": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/chromium-pickle-js/-/chromium-pickle-js-0.2.0.tgz", - "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==", - "dev": true + "integrity": "sha512-1R5Fho+jBq0DDydt+/vHWj5KJNJCKdARKOCwZUen84I5BreWoLqRLANH1U87eJy1tiASPtMnGqJJq0ZsLoRPOw==" }, "clean-stack": { "version": "2.2.0", diff --git a/package.json b/package.json index b542ce1..f04f5e7 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "author": "samuel", "license": "MIT", "dependencies": { + "asar": "^3.2.0", "axios": "^1.2.2", "electron-squirrel-startup": "^1.0.0", "selenium-webdriver": "^4.5.0" diff --git a/updater.cpp b/updater.cpp index 875f72d..a03d9de 100644 --- a/updater.cpp +++ b/updater.cpp @@ -7,6 +7,7 @@ int main() Sleep(1000); remove("app.asar"); rename("app.asar-new","app.asar"); + Sleep(1000); ShellExecute(0,"open", "..\\network_class.exe", 0, 0, 1); return 0; } diff --git a/updater.exe b/updater.exe index 1f80df1fade468ce4521cef79ebb67c13ecec4f9..440eeaed261cca08942fb7acbd120295bb197a1a 100644 GIT binary patch delta 8318 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 delta 8320 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