使用pkg打包Node.js应用调用外部可执行文件时出现ENOENT错误
问题:pkg打包后execFile调用exe出现ENOENT错误(本地运行正常)
本地环境中使用child_process.execFile调用可执行文件一切正常,但通过pkg工具打包成exe后运行,出现ENOENT错误。已通过fs.existsSync()确认文件路径返回true,但仍无法执行。
相关信息
业务代码(index.js)
const { execFile } = require("child_process"); const fs = require("fs"); const execDirectory = path.join(__dirname, "./executables"); const determineActiveWindows = async (appDataDirectory) => { const command = `${execDirectory}\\determineActiveWindows.exe`; console.log("file exists", fs.existsSync(command)); console.log("command", command); execFile( command, ["--appDataDirectory", appDataDirectory], (err, stdout, sterr) => { if (err) console.error(err); if (stdout) console.log(stdout); if (sterr) console.error(sterr); } ); };
错误日志
file exists true command C:\snapshot\MinimizeWindows\build\app\executables\determineActiveWindows.exe Error: spawn C:\snapshot\MinimizeWindows\build\app\executables\determineActiveWindows.exe ENOENT at Process.ChildProcess._handle.onexit (node:internal/child_process:283:19) at onErrorNT (node:internal/child_process:478:16) at processTicksAndRejections (node:internal/process/task_queues:83:21) at process.runNextTicks [as _tickCallback] (node:internal/process/task_queues:65:3) at Function.runMain (pkg/prelude/bootstrap.js:1984:13) at node:internal/main/run_main_module:17:47 { errno: -4058, code: 'ENOENT', syscall: 'spawn C:\\snapshot\\MinimizeWindows\\build\\app\\executables\\determineActiveWindows.exe', path: 'C:\\snapshot\\MinimizeWindows\\build\\app\\executables\\determineActiveWindows.exe', spawnargs: [ '--appDataDirectory', 'appName' ], cmd: 'C:\\snapshot\\MinimizeWindows\\build\\app\\executables\\determineActiveWindows.exe --appDataDirectory appName' }
项目目录结构
-build ---app ------executables ---------determineActiveWindows.exe ------index.js
pkg打包命令
pkg -c package.json build/app/index.js
package.json中的pkg配置
"pkg": { "targets": ["node16-win-x64"], "scripts": "build/**/*.js", "assets": "build/**/*", "outputPath": "dist" }
解决方法
1. 修正exe路径获取逻辑(核心修复)
pkg的快照目录是虚拟的,__dirname指向的是打包时的快照路径,并非运行时实际文件所在路径。需要通过process.execPath获取打包后主exe的实际目录,再拼接目标exe路径:
修改后的代码:
const { execFile } = require("child_process"); const fs = require("fs"); const path = require("path"); // 补上缺失的path模块引入 // 获取打包后主exe所在的实际目录 const appExecDir = path.dirname(process.execPath); // 拼接目标exe的实际路径 const command = path.join(appExecDir, "executables", "determineActiveWindows.exe"); const determineActiveWindows = async (appDataDirectory) => { console.log("file exists", fs.existsSync(command)); console.log("command", command); execFile( command, ["--appDataDirectory", appDataDirectory], (err, stdout, sterr) => { if (err) console.error(err); if (stdout) console.log(stdout); if (sterr) console.error(sterr); } ); };
2. 优化pkg的assets配置
当前assets配置范围过广,可能导致资源识别异常,改为仅打包需要的exe文件:
"pkg": { "targets": ["node16-win-x64"], "scripts": "build/**/*.js", "assets": "build/app/executables/**/*.exe", // 精确匹配需要的exe "outputPath": "dist" }
3. 应急变通:使用exec替代execFile
若上述方法仍未解决,可尝试通过系统shell执行命令(exec会调用shell处理路径):
const { exec } = require("child_process"); // ... 其他路径逻辑不变 exec(`${command} --appDataDirectory ${appDataDirectory}`, (err, stdout, sterr) => { if (err) console.error(err); if (stdout) console.log(stdout); if (sterr) console.error(sterr); });
4. 手动验证资源打包情况
打包完成后,检查dist目录下是否存在executables文件夹及对应exe文件。若缺失,手动复制build/app/executables到dist目录后再测试。
内容的提问来源于stack exchange,提问作者Arky Asmal
相关产品推荐
相关产品推荐

