electron-forge使用better-sqlite3时安装卸载报目录不存在错误
报错原因
- Electron Forge 针对 Windows 平台默认使用 NSIS 打安装包,默认会在安装、卸载流程中提前启动一次应用主进程执行快捷方式创建、残留文件清理等钩子逻辑。此时应用资源还未完全解压部署到目标安装目录,且钩子阶段启动主进程的工作目录和正常启动应用的工作目录不一致,你在主进程顶层作用域直接同步初始化数据库,就会触发目录不存在的报错。
- 你写的生产环境数据库路径为相对路径,相对路径会基于进程启动时的工作目录计算,安装/卸载钩子阶段的工作目录并非应用安装目录,拼接出来的路径完全错误,进一步导致找不到目标目录。
- 该报错仅出现在钩子执行阶段,不会影响后续安装流程,安装完成后正常启动应用时路径符合预期,所以运行功能正常。
修复方案
- 优先处理安装/卸载钩子逻辑,直接跳过业务代码执行
Electron Forge 模板默认自带electron-squirrel-startup依赖,专门用于识别钩子启动场景,在主进程最顶部加入如下代码即可:
import { app } from 'electron'; if (require('electron-squirrel-startup')) app.quit();
- 调整数据库初始化时机与路径规则
不要在主进程顶层同步初始化数据库,将初始化逻辑移到app.whenReady()回调中,同时生产环境不要使用相对路径,通过内置API获取正确的资源路径,额外加目录存在性判断:
import fs from 'fs-extra'; import path from 'path'; import Database from 'better-sqlite3'; let db: Database.Database | null = null; app.whenReady().then(() => { const isDevEnv = !app.isPackaged; const dbPath = isDevEnv ? path.join(app.getAppPath(), "src", "data", "db.db") : path.join(process.resourcesPath, "app", ".webpack", "data", "db.db"); // 目录不存在则先创建,避免报错 const dbDir = path.dirname(dbPath); if (!fs.existsSync(dbDir)) { fs.mkdirSync(dbDir, { recursive: true }); } db = new Database(dbPath, { verbose: console.log }); // 后续窗口创建等业务逻辑 })
- 可选:调整数据库存储位置(适配写入需求)
如果你后续需要向数据库写入数据,不要把数据库放在打包的只读资源目录中,首次启动时把预置数据库拷贝到用户数据目录,所有读写都用该路径,既没有权限问题,也不会被版本更新覆盖:
const userDbPath = path.join(app.getPath('userData'), 'db.db'); if (!fs.existsSync(userDbPath)) { // 把预置的打包资源目录里的数据库拷贝到用户目录 const presetDbPath = path.join(process.resourcesPath, "app", ".webpack", "data", "db.db"); fs.copyFileSync(presetDbPath, userDbPath); } // 用userDbPath初始化数据库
内容的提问来源于stack exchange,提问作者Ian Natividad
相关产品推荐
相关产品推荐

