如何在Electron preloader脚本中访问app路径调用getPath获取userData
报错原因
app是Electron主进程专属模块,无法在渲染进程侧的Preload脚本中直接引入使用,因此你require得到的app值为undefined,调用getPath方法自然会抛出报错。
可行解决方案
以下两种方案均可实现需求,可根据自身项目逻辑选择:
方案1:通过IPC从主进程获取路径
无需修改现有配置逻辑,适配所有Electron版本和沙箱配置
- 修改主进程代码,新增IPC监听
const { ipcMain, app } = require('electron') // 同步获取路径的监听 ipcMain.on('get-user-data-path', (event) => { event.returnValue = app.getPath('userData') }) // 异步获取路径的监听(推荐非阻塞调用使用) ipcMain.handle('get-user-data-path-async', () => { return app.getPath('userData') })
- 修改Preload脚本,对应暴露调用方法
const { contextBridge, ipcRenderer } = require('electron'); let os = require("os"); contextBridge.exposeInMainWorld('electron', { ipcRenderer: { myPing() { ipcRenderer.send('ipc-example', 'ping'); }, on(channel, func) { const validChannels = ['ipc-example',]; if (validChannels.includes(channel)) { ipcRenderer.on(channel, (event, ...args) => func(...args)); } }, once(channel, func) { const validChannels = ['ipc-example']; if (validChannels.includes(channel)) { ipcRenderer.once(channel, (event, ...args) => func(...args)); } }, // 新增同步获取路径方法 getStoragePathSync: () => ipcRenderer.sendSync('get-user-data-path'), // 新增异步获取路径方法 getStoragePathAsync: () => ipcRenderer.invoke('get-user-data-path-async') }, os:{ cpuCount: os.cpus().length, } });
渲染层调用时同步直接取返回值,异步方法加await调用即可。
方案2:主进程写入环境变量直接读取
写法更简单,和你原有暴露逻辑完全兼容
- 主进程创建窗口前写入环境变量
// 主进程app初始化完成后添加 process.env.ELECTRON_USER_DATA_PATH = app.getPath('userData')
如果开启了渲染进程沙箱,环境变量不会自动同步,需要在创建窗口时通过参数传递:
const win = new BrowserWindow({ webPreferences: { preload: path.join(__dirname, 'preload.js'), additionalArguments: [`--user-data-path=${app.getPath('userData')}`] } })
- Preload脚本直接读取路径
const { contextBridge, ipcRenderer } = require('electron'); let os = require("os"); // 未开沙箱直接读环境变量 const localPath = process.env.ELECTRON_USER_DATA_PATH // 开启沙箱则从启动参数读取 // const localPath = process.argv.find(arg => arg.startsWith('--user-data-path=')).split('=')[1] contextBridge.exposeInMainWorld('electron', { // 原有ipcRenderer、os代码保留 ipcRenderer: { myPing() { ipcRenderer.send('ipc-example', 'ping'); }, on(channel, func) { const validChannels = ['ipc-example',]; if (validChannels.includes(channel)) { ipcRenderer.on(channel, (event, ...args) => func(...args)); } }, once(channel, func) { const validChannels = ['ipc-example']; if (validChannels.includes(channel)) { ipcRenderer.once(channel, (event, ...args) => func(...args)); } }, }, os:{ cpuCount: os.cpus().length, }, storage:{ localPath: localPath } });
注意:不推荐使用
@electron/remote模块实现该需求,该模块默认已被禁用,且会引入额外的安全风险。
内容的提问来源于stack exchange,提问作者chipimix
相关产品推荐
相关产品推荐

