使用 electron-builder 时 SpawnSync 不起作用
SpawnSync doesn't work when using electron-builder
我正在编写一个 react-electron 应用程序,我注意到当我使用 electron-builder 构建它时,二进制文件在调用“spawn”时卡住了。
使用“yarn start”可以毫无问题地执行应用程序。只有 electron-builder 才会卡住。
你能帮忙吗?
谢谢,
更新
作为程序的一部分包含的 C++ 二进制文件似乎无法在 electron 中执行。如果我给出二进制文件的硬编码完整路径,它就可以工作,但是如果我给出 __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
根据亚历山大的建议,我已经包括在内
"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/../cpp_program/.
中没有“helloWorldRepeat”文件
二进制文件实际上位于
/Users/Rick/projects/lala/github/tutorial/electron-tutorial-app/build/../cpp_program/helloWorldRepeat
我是否必须手动创建此文件夹并粘贴二进制文件?
默认情况下,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/")
我正在编写一个 react-electron 应用程序,我注意到当我使用 electron-builder 构建它时,二进制文件在调用“spawn”时卡住了。
使用“yarn start”可以毫无问题地执行应用程序。只有 electron-builder 才会卡住。
你能帮忙吗?
谢谢,
更新
作为程序的一部分包含的 C++ 二进制文件似乎无法在 electron 中执行。如果我给出二进制文件的硬编码完整路径,它就可以工作,但是如果我给出 __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
根据亚历山大的建议,我已经包括在内
"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/../cpp_program/.
中没有“helloWorldRepeat”文件二进制文件实际上位于
/Users/Rick/projects/lala/github/tutorial/electron-tutorial-app/build/../cpp_program/helloWorldRepeat
我是否必须手动创建此文件夹并粘贴二进制文件?
默认情况下,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/")