如何使用 Electron 运行和打包外部可执行文件?

2023-11-21

例如,我有一个编译好的二进制文件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 is /,所以我得到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不过没关系,我可以换到另一个建筑商。


有两件事。如果你设置__dirname: true在你的网络应用程序配置中你会得到relative上下文目录中的文件路径

如果你设置__dirname: false then __dirname将有完整的路径。

发展模式

你有两个选择

  1. Set __dirname: true并将其与os.cwd()
  2. Set __dirname: false并使用__dirname直接地

生产模式

  1. Set __dirname: true并使用os.cwd().
  2. Set __dirname: true并使用process.resourcePath

我更喜欢 2 作为生产中的首选方法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何使用 Electron 运行和打包外部可执行文件? 的相关文章

随机推荐

  • MenuItemCompat.getActionView 始终返回 null

    我刚刚实施了v7 AppCompat支持库但是MenuItemCompat getActionView在我测试的每个 Android 版本中总是返回 null 4 2 2 2 3 4 The SearchView显示在操作栏中 但它不响应触
  • UDP(数据报)套接字的 FIONREAD 返回什么? [复制]

    这个问题在这里已经有答案了 哪一个做ioctl of FIONREAD返回 下一个数据包的长度 还是缓冲区中所有数据的长度 假设有一个UDP服务器接收来自客户端 1 的 2 个数据包 并在客户端 1 的数据包之后接收来自客户端 2 的另外
  • 构造函数中的异常

    在 C 中 对象的生命周期从构造函数成功完成时开始 在构造函数内部 该对象还不存在 问 从构造函数发出异常意味着什么 答 这意味着构造失败 该对象从未存在过 其生命周期从未开始 source 我的问题是 Java 也是如此吗 例如 如果我把
  • 如何从Powershell获取退出代码并返回CMD?

    我有一个 powershell 脚本 我使用 CMD 文件运行 powershell 脚本 我想从 powershell 脚本中获取退出代码并将值返回给 CMD 我试过这个 但当我执行 CMD 文件来调用 powershell 时 它不会返
  • 无法在 Visual Studio 2013 中打开 Web 项目

    昨天我安装了 Visual Studio 2013 的更新 Visual Studio 2013 Update 2 但从那时起它就无法正常工作 更新花费了相当长的时间 所以我让它运行了一夜 当我今天早上回到我的工作站时 我无法在我们的解决方
  • “Rscript”不被识别为内部或外部命令、可操作程序或批处理文件

    shell exec Rscript C R R 3 2 2 bin code R 这是对脚本的调用 调用上述脚本时 会发生错误 我试图从上述路径调用我的 R 脚本 但没有显示任何输出 在检查 PHP 的错误日志时 它说 Rscript 未
  • 为什么Matlab和Octave中inv()和pinv()的输出不相等?

    我注意到如果 A 是一个 NxN 矩阵并且它有逆矩阵 但是 inv 和 pinv 函数输出的内容是不同的 我的环境是Win7x64 SP1 Matlab R2012a Cygwin Octave 3 6 4 FreeMat 4 2 看看 O
  • 向 requestAnimationFrame 回调的函数添加额外的参数

    我希望创建一个函数 使用 requestAnimationFrame 和增量时间在 HTML5 画布上将图像元素滚动 x 像素超过 y 时间 我不知道的是 当 requestAnimationFrame allready 使用一个参数 DO
  • 上下文中的多个包:组件扫描、spring config

    如何在 spring servlet xml 文件中添加多个包context component scan元素 我努力了
  • 如何使用 TensorFlow 2.0 打乱两个 numpy 数据集?

    我想写一个函数TensorFlow 2 0比在每次训练迭代之前对数据及其目标标签进行打乱 假设我有两个 numpy 数据集 X 和 y 代表用于分类的数据和标签 我怎样才能洗牌同时 Using sklearn这很简单 from sklear
  • 扩展 Android 的语音搜索应用

    是否可以扩展语音搜索应用程序 我知道我可以在自己的应用程序中添加一个按钮来启动语音识别对话框 但我想知道是否可以扩展当您长按物理 搜索 键时自动启动的语音搜索应用程序 send text to contact message listen
  • 关于 Vue 3 + TypeScript 和 Augmenting-Types-for-Use-with-Plugins 的问题

    有谁知道如何使用 Vue3 和 TypeScript 实现类型增强的工作示例 我一直在尝试遵循 Vue2 文档 在 Vue3 中使用相同的内容 但没有成功 并且在过去 3 个小时的搜索中没有任何结果 看来Vue对象在vue class co
  • 检查矩阵行是否等于 R 中的矢量(矢量化)

    我很惊讶这个问题没有被问到 也许答案会澄清原因 我想将矩阵的行与向量进行比较 并返回该行是否 处处的向量 请参阅下面的示例 我想要一个矢量化解决方案 没有应用函数 因为矩阵太大而无法缓慢循环 假设也有很多行 所以我想避免重复向量 set s
  • 将 Microsoft SQL 复制到其他数据库

    我希望能够将整个数据库从 Microsoft SQL 复制到另一个 Web 友好的数据库 例如 CouchDB 甚至 mySQL 我需要每天进行复制 只是想知道是否可能 如果可以 我将如何用最少的编码来完成它 Thanks 这是可能的对称D
  • 在网页上查找广告

    我正在编写一个应用程序 试图确定页面上是否有广告 当前正在使用 python 通过 selenium webdriver 使用浏览器驱动 我认为 iframe 内存在大量广告 并且我制作了一个循环来查看每个框架的内部 browser web
  • AngularJS 中用于分页的限制和偏移数据结果

    AngularJS在调用支持Limit和Offset的外部数据资源时是否有Limit和Offset请求方法 我想有一个比这更优雅的解决方案 我通过路线参数传递限制和偏移量 function ListCtrl scope http route
  • ExecCommand 函数的定义是否为粗体?

    ExecCommand 提供了一种在 iFrame 中将文本加粗 斜体 下划线等的方法 但它缺少创建选项
  • Flask WTF“StringField”对象没有属性“translate”

    我对 Python 比较陌生 并且一直在关注Miguel Grinberg Flask 超级教程 我有一个非常简单的表单 当我尝试提交时 我收到以下错误 AttributeError StringField 对象没有属性 translate
  • Postgresql join_collapse_limit 和查询规划的时间

    我刚刚发现join collapse limit一直在阻止 PostgreSQL 规划器找到更好的连接顺序 就我而言 将限制增加到 10 默认为 8 允许规划器将搜索时间从约 30 秒缩短到约 1 毫秒 这是更容易接受的 该文档表明 设置此
  • 如何使用 Electron 运行和打包外部可执行文件?

    例如 我有一个编译好的二进制文件cudaDeviceQuery它以 JSON 形式返回设备列表 这是一段代码 export default function cudaDeviceQuery Promise