如何使用 Electron 运行和打包外部可执行文件?
Posted
技术标签:
【中文标题】如何使用 Electron 运行和打包外部可执行文件?【英文标题】:How to run and pack external executable using Electron? 【发布时间】:2018-08-06 19:32:16 【问题描述】:例如,我有一个已编译的二进制文件cudaDeviceQuery
,它以 JSON 形式返回设备列表。这是一段代码:
export default function cudaDeviceQuery(): Promise<CollectorResponse>
const throwError = () =>
throw new Error("Unfortunately your platform isn't yet unsupported");
;
const file = __DARWIN__
? path.join(__dirname, 'darwin', 'cudaDeviceQuery')
: __WIN32__
? path.join(__dirname, 'win', 'cudaDeviceQuery.exe')
: throwError();
const descriptor = spawn(file);
return new Promise((resolve, reject) =>
let outerData = '';
descriptor.stdout.on('data', data =>
outerData += data;
);
descriptor.on('close', () =>
try
resolve(JSON.parse(outerData));
catch (e)
reject(e);
);
);
但是当我从渲染器进程中使用这个函数时,__dirname
是/
,所以我得到spawn /darwin/cudaDeviceQuery ENOENT
错误。在开发环境中生成它并将其打包到生产环境中的正确方法是什么?
一个 webpack 配置:
webpack.config.base.js
:
/**
* Base webpack config used across other specific configs
*/
const webpack = require('webpack');
const path = require('path');
const getReplacements = require('./app/app-info').getReplacements;
const dependencies: externals = require('./app/renderer/package.json');
module.exports =
module:
noParse: [path.join(__dirname, 'node_modules/ws')],
rules: [
test: /\.tsx?$/,
use: [
loader: 'babel-loader',
,
loader: 'ts-loader',
,
],
exclude: /node_modules/,
,
],
,
output:
path: path.join(__dirname, 'app', 'renderer'),
filename: 'bundle.js',
libraryTarget: 'commonjs2',
,
// https://webpack.github.io/docs/configuration.html#resolve
resolve:
extensions: ['.js', '.ts', '.tsx', 'json'],
modules: [path.join(__dirname, 'app', 'renderer'), 'node_modules'],
,
plugins: [new webpack.DefinePlugin(getReplacements())],
externals: [...Object.keys(externals || ), 'ws'],
;
webpack.config.development.js
:
/**
* Build config for development process that uses Hot-Module-Replacement
* https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
*/
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.base');
const getReplacements = require('./app/app-info').getReplacements;
const port = process.env.PORT || 3000;
module.exports = merge(baseConfig,
devtool: 'inline-source-map',
entry: [
'react-hot-loader/patch',
`webpack-hot-middleware/client?path=http://localhost:$port/__webpack_hmr&reload=true`,
'./app/renderer/index',
],
output:
publicPath: `http://localhost:$port/dist/`,
,
module:
rules: [
// Css, SCSS, woff loaders are here
],
,
plugins: [
// https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
new webpack.HotModuleReplacementPlugin(),
new webpack.LoaderOptionsPlugin(
debug: true,
),
],
// https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
target: 'electron-renderer',
);
webpack.config.electron.js
:
/**
* Build config for electron 'Main Process' file
*/
const webpack = require('webpack');
const merge = require('webpack-merge');
const baseConfig = require('./webpack.config.base');
const getReplacements = require('./app/app-info').getReplacements;
module.exports = merge(baseConfig,
devtool: 'source-map',
entry: ['./app/main/index.ts'],
// 'main.js' in root
output:
path: __dirname,
filename: './app/main/main.js',
,
plugins: [
// Add source map support for stack traces in node
// https://github.com/evanw/node-source-map-support
// new webpack.BannerPlugin(
// 'require("source-map-support").install();',
// raw: true, entryOnly: false
// ),
],
/**
* Set target to Electron specific node.js env.
* https://github.com/chentsulin/webpack-target-electron-renderer#how-this-module-works
*/
target: 'electron-main',
/**
* Disables webpack processing of __dirname and __filename.
* If you run the bundle in node.js it falls back to these values of node.js.
* https://github.com/webpack/webpack/issues/2010
*/
node:
__dirname: false,
__filename: false
,
);
如您所见,我正在使用开发服务器进行热模块更换,所以也许这就是原因...我有server.js
使用脚本创建服务器,然后我从主进程中使用它。这里是server.js
:
/**
* Setup and run the development server for Hot-Module-Replacement
* https://webpack.github.io/docs/hot-module-replacement-with-webpack.html
*/
const argv = require('minimist')(process.argv.slice(2));
const spawn = require('child_process');
async function createMiddleware(port, configPath)
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const webpackHotMiddleware = require('webpack-hot-middleware');
const config = require(configPath);
const app = express();
const compiler = webpack(config);
const PORT = process.env.PORT || port;
const wdm = webpackDevMiddleware(compiler,
publicPath: config.output.publicPath,
stats:
colors: true,
,
);
app.use(wdm);
app.use(webpackHotMiddleware(compiler));
const server = app.listen(PORT, serverError =>
if (serverError)
return console.error(serverError);
console.log(`Listening at http://localhost:$PORT`);
);
process.on('SIGTERM', () =>
console.log('Stopping dev server');
wdm.close();
server.close(() =>
process.exit(0);
);
);
createMiddleware(3000, './webpack.config.development'); // A main renderer process
createMiddleware(3010, './webpack.config.server'); // A backend for communicating between renderer and remote server
if (argv['start-hot'])
spawn('npm', ['run', 'start-hot'],
shell: true,
env: process.env,
stdio: 'inherit',
)
.on('close', code => process.exit(code))
.on('error', spawnError => console.error(spawnError));
换句话说,我需要从电子渲染器进程中调用cudaDeviceQuery
库。我使用的是electron-builder
,不过没关系,我可以切换到另一个构建器。
【问题讨论】:
请将您的 webpack 配置添加到问题中 @TarunLalwani 好的,已添加 有两种方法。您可以使用process.cwd()
或process.resourcePath
,而不是依赖__dirname
。在开发中,您可以在调用__dirname
时使用__dirname: true
获取完整路径。但是对于生产,您需要使用两种方法之一
不幸的是,如果我将webpack.config.electron.js
中的__dirname
设置为true,我会收到Not allowed to load local resource: file://app/renderer/app.html
错误。 process.cwd()
帮助!但我不确定这对生产有什么好处(如果应用程序不是从他们的目录中调用的)。我发现了另一种方法:__dirname
在主进程中完美运行,因此我可以通过 ipc 获取文件的完整路径。你能提交你的答案,然后我会接受吗?
【参考方案1】:
有两件事。如果您在 Web 应用配置中设置 __dirname: true
,您将从上下文目录中获取文件的 relative
路径
如果您设置了__dirname: false
,那么__dirname
将拥有完整路径。
开发模式
你有两个选择
-
设置
__dirname: true
并将其与os.cwd()
连接
设置__dirname: false
,直接使用__dirname
生产模式
-
设置
__dirname: true
并使用os.cwd()
。
设置__dirname: true
并使用process.resourcePath
我更喜欢 2 作为生产中的首选方法
【讨论】:
【参考方案2】:将此添加到package.json
:
"scripts":
"start": "electron .", "install": "electron-rebuild",
"package-osx": "electron-packager . Node-RED --platform=darwin --arch=x64 -- out=build --overwrite",
"package-mac": "electron-packager . --overwrite --platform=darwin --arch=x64 --prune=true --out=release-builds",
"package-win": "electron-packager . electron-serialport --overwrite --asar=true --platform=win32 --arch=x64 --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"CryptoApp\"",
"package-linux": "electron-packager . electron-serialport --overwrite --asar=true --platform=linux --arch=x64 --prune=true --out=release-builds"
,
"dependencies":
"electron-packager": "^12.1.0",
"electron-prebuilt": "^1.4.13",
如果不适用于 windows,请使用以下内容:
"package-win": "electron-packager . electron-serialport --overwrite --asar=true --platform=win32 --arch=ia32 --prune=true --out=release-builds --version-string.CompanyName=CE --version-string.FileDescription=CE --version-string.ProductName=\"CryptoApp\"",
谢谢...
【讨论】:
以上是关于如何使用 Electron 运行和打包外部可执行文件?的主要内容,如果未能解决你的问题,请参考以下文章