【问题标题】:SpawnSync doesn't work when using electron-builder使用电子生成器时 SpawnSync 不起作用
【发布时间】:2021-05-16 15:29:10
【问题描述】:

我正在编写一个 react-electron 应用程序,我注意到当我使用 electron-builder 构建它时,二进制文件在调用“spawn”时被卡住了。

使用“yarn start”可以毫无问题地执行应用程序。只有使用电子生成器才会卡住。

你能帮忙吗?

谢谢,

更新

似乎作为程序一部分包含的 C++ 二进制文件无法在电子中执行。如果我给出二进制文件的硬编码完整路径,它可以工作,但如果我给出 __dirname 的路径,我会收到错误

const GetLocalPath = () => {
  const path = __dirname + "/../cpp_program/"

  return {
    helloWorld: path+ "helloWorld",
    helloWorldRepeat: path+ "helloWorldRepeat"
  }
}

export function helloWorld(){
  // let dir = "/Users/Rick/projects/lala/github/tutorial/electron-tutorial-app/cpp_program";
  let comm = GetLocalPath().helloWorld;

错误信息

internal/child_process.js:403 Uncaught (in promise) Error: spawn ENOTDIR
    at ChildProcess.spawn (internal/child_process.js:403)
    at Object.spawn (child_process.js:562)
    at helloWorldRepeat (/Users/ricky/proje…ar/build/Lib.js:113)
    at Object.<anonymous> (/Users/ricky/proje…sar/build/Lib.js:49)
    at Generator.next (<anonymous>)
    at /Users/ricky/proje…asar/build/Lib.js:9
    at new Promise (<anonymous>)
    at __awaiter (/Users/ricky/proje…asar/build/Lib.js:5)
    at Object.handleInitialize (/Users/ricky/proje…sar/build/Lib.js:35)
    at TestStateMachine.transition (/Users/ricky/proje…tStateMachine.js:56)

这很奇怪,因为它与“yarn start”(即“tsc && electron”)配合得很好

package.json 如下所示

  "scripts": {
    "start": "tsc && electron ."
  },
  "build": {
    "appId": "com.example.myapp",
    "productName": "MyApp",
    "files": [
      "build/**/*",
      "public/**/*",
      "src/images/**/*"
    ]
  }, 

更新版本 2

根据 Alexander 的建议,我已包括在内

"asar": false

在 package.json 中

当我执行它时,我得到一个不同的错误

Uncaught Error: spawn /Users/Rick/projects/lala/github/tutorial/electron-tutorial-app/dist/mac/MyApp.app/Contents/Resources/app/build/../cpp_program/helloWorldRepeat ENOENT
    at Process.ChildProcess._handle.onexit (internal/child_process.js:269)
    at onErrorNT (internal/child_process.js:465)
    at processTicksAndRejections (internal/process/task_queues.js:80)
errnoException  @   internal/errors.js:510
ChildProcess._handle.onexit @   internal/child_process.js:269
onErrorNT   @   internal/child_process.js:465
processTicksAndRejections   @   internal/process/task_queues.js:80

现在的错误是 /Users/Rick/projects/lala/github/tutorial/electron-tutorial-app/dist/mac/MyApp.app/Contents/Resources/app/build 中没有“helloWorldRepeat”文件/../cpp_program/.

二进制文件实际上位于

/Users/Rick/projects/lala/github/tutorial/electron-tutorial-app/build/../cpp_program/helloWorldRepeat

我必须手动创建这个文件夹并粘贴二进制文件吗?

【问题讨论】:

    标签: reactjs electron electron-builder spawn


    【解决方案1】:

    默认情况下,Electron Builder 编译您的应用程序并将所有资源打包到一个大型存档文件(将其视为 ZIP 文件),因为 Electron 支持这种称为“ASAR”的格式,所以可以很好地阅读。

    运行构建的程序时,将从存档中读取代码。这意味着__dirname 将指向存档内的一个目录。但是,操作系统无法从存档中读取。由于您实际上并未包含调用child_process.spawn () 的代码段,因此我只能推测您为什么会得到ENOTDIR,这暗示给定路径不是目录,而预期它是一个目录,但我认为这是因为您指向 ASAR 文件中的路径。

    当依赖外部二进制文件时,最好将它们保留在 ASAR 存档之外并以编程方式找到它们的路径(这非常复杂),或者阻止 Electron Builder 将您的应用程序编译成 ASAR 文件。但是,您还必须要求 Electron Builder 将可执行文件包含在应用程序的构建版本中。这可以通过修改你的package.json来完成:

    {
        ...
        "build": {
            "appId": "com.example.myapp",
            "productName": "MyApp",
            "files": [
                "build/**/*",
                "public/**/*",
                "src/images/**/*"
            ],
            "extraResources": [
                "cpp_program/*"
            ]
            "asar": false
        },
    }
    

    (将"cpp_program/*"替换为与您所需目录匹配的任何路径模式,如果有子目录,甚至可能将/*替换为/**/*。)

    这样,cpp_program 目录将在构建时复制到您应用的资源目录中。根据Electron Builder's documentation,这条路径在MacOS 上是Contents/Resources/。因此,您将不得不修改您的路径(__dirname + "../" 将不起作用,因为它将指向 Contents/Resources/app,但 __dirname + "../../" 应该;如果不是,试验将导致正确的路径)*。请记住每次 C++ 可执行文件更改时运行 Electron Builder,因为 .app 文件夹中的文件未链接到已构建应用程序之外的对应文件。


    *你可以通过检查__dirname.includes (".app/")是否在开发路径(__dirname + "../")和生产路径(__dirname + "../../"或其他)之间切换

    【讨论】:

    • 我尝试了您的建议,现在出现“ENOENT”错误,因为此目录中不存在二进制文件。这是否意味着我必须将二进制文件移动到该位置?让我更新我的帖子。
    • @takanoha 请查看更新后的答案。您还必须包含二进制文件的目录。
    • 我明白了。是的,它确实有效,但二进制文件没有作为应用程序的一部分捆绑在一起。使用“npx electron-builder --mac --x64 --dir”我可以看到应用程序是在这里构建的“dist/mac/MyApp.app”,它将在 cpp_program 中动态调用 helloWorldRepeat。有没有办法将所有这些捆绑在 MyApp.app 中?
    • 这就是 Electron Builder 配置的 "include": [] 部分中的新行应该做的。 .apps 只是目录,你应该可以在 Finder 中输入它并检查它是否真的被复制到 dist/mac/MyApp.app/Content/Resources/app 文件夹中(虽然不是 Mac 用户,所以无法帮助你)。
    • Alex,我还是很疑惑。您能否使用“include”关键字更新 package.json,以便将二进制文件复制到 MyApp.app/ 内部?
    猜你喜欢
    • 2020-08-12
    • 2021-06-10
    • 2019-03-03
    • 2018-04-26
    • 2021-02-11
    • 2015-11-14
    • 2017-12-30
    • 2020-05-14
    • 2016-08-20
    相关资源
    最近更新 更多