回答此问题可获得+50声望bounty。赏金宽限期已经结束。th3g3ntl3man正在寻找一个规范答案。
我创建了一个电子和React的应用程序。此应用程序有一个内部C++服务器。在开发模式下,我没有问题,但在打包后,服务器无法启动。
这是我的文件夹树:
├── dist-electron
│ ├── main
│ └── preload
├── electron
│ ├── main
│ └── preload
├── public
│ └── tmp
├── server
└── src
├── @types
├── api
├── assets
├── common
├── components
├── context
├── routes
└── theme
server文件夹在react build后包含在dist文件夹中。
在electron main中我写了这个函数:
try {
const appPath = app.isPackaged
? join(process.env.PUBLIC, '../../server')
: join(process.env.DIST_ELECTRON, '../server');
const server = spawn(
join(appPath, 'operations'),
[
join(appPath, 'settings.json'),
join(appPath, '../public/tmp'),
],
{ cwd: appPath }
);
server.stdout.on('data', (data) => {
console.log(`Server stdout: ${data}`);
});
server.stderr.on('data', (data) => {
console.error(`Server stderr: ${data}`);
});
server.on('close', (code) => {
console.log(`Server process exited with code ${code}`);
});
}
catch (err) {
dialog.showMessageBox(DialDesigner.main!, { title: 'Errore', message: process.env.PUBLIC });
app.quit();
}
其中:
process.env.DIST_ELECTRON = join(__dirname, '../');
process.env.DIST = join(process.env.DIST_ELECTRON, '../dist');
process.env.PUBLIC = process.env.VITE_DEV_SERVER_URL ?
join(process.env.DIST_ELECTRON, '../public') :
process.env.DIST;
我总是把spawn ENOTDIR
作为错误。我解压缩app.asar文件,操作可执行文件存在于正确的目录dist/server
中
下面是electron-builder.json5
配置文件:
/**
* @see https://www.electron.build/configuration/configuration
*/
{
"appId": "it.softwaves.dial-designer",
"productName": "Dial Designer",
"asar": true,
"directories": {
"output": "release/${version}"
},
"files": [
"dist-electron",
"dist",
"server"
],
"mac": {
"artifactName": "Dial_Designer_${version}.${ext}",
"target": [
"dmg",
"zip"
]
},
"win": {
"target": [
{
"target": "nsis",
"arch": [
"x64"
]
}
],
"artifactName": "Dial_Designer_${version}.${ext}"
},
"nsis": {
"oneClick": false,
"perMachine": false,
"allowToChangeInstallationDirectory": true,
"deleteAppDataOnUninstall": false
},
"publish": {
"provider": "generic",
"channel": "latest",
"url": "https://github.com/electron-vite/electron-vite-react/releases/download/v0.9.9/"
}
}
这是一个DialDesigner.ts
类,用于示例和配置电子应用程序:
import { join, dirname } from 'node:path';
import { release } from 'node:os';
import { spawn } from 'node:child_process';
import { copySync } from 'fs-extra';
import {
app, BrowserWindow, screen,
shell, Menu, MenuItemConstructorOptions, dialog
} from 'electron';
import { update } from './update';
interface IWin {
title: string,
width: number,
height: number,
preload?: any,
resizable?: boolean,
}
export default class DialDesigner {
public static main: BrowserWindow | null;
public static settings: BrowserWindow | null;
public static url: string | undefined;
public static indexHtml: string;
public static IS_MAC: boolean = process.platform === 'darwin';
constructor() {
process.env.DIST_ELECTRON = join(__dirname, '../');
process.env.DIST = join(process.env.DIST_ELECTRON, '../dist');
process.env.PUBLIC = process.env.VITE_DEV_SERVER_URL ?
join(process.env.DIST_ELECTRON, '../public') :
process.env.DIST;
DialDesigner.url = process.env.VITE_DEV_SERVER_URL;
DialDesigner.indexHtml = join(process.env.DIST, 'index.html');
if (release().startsWith('6.1')) app.disableHardwareAcceleration();
if (process.platform === 'win32') app.setAppUserModelId(app.getName());
if (!app.requestSingleInstanceLock()) {
app.quit();
process.exit(0);
}
}
public static newWindow = (win: IWin): BrowserWindow => {
return new BrowserWindow({
title: win.title,
icon: join(process.env.PUBLIC, 'favicon.ico'),
width: win.width,
height: win.height,
center: true,
resizable: win.resizable ?? true,
webPreferences: {
preload: win?.preload,
nodeIntegration: true,
contextIsolation: false,
},
});
}
private runServer = () => {
let appPath = null;
try {
appPath = app.isPackaged
? join(process.env.DIST, '../server')
: join(process.env.DIST_ELECTRON, '../server');
const server = spawn(
join(appPath, 'operations'),
[
join(appPath, 'settings.json'),
join(appPath, '../public/tmp'),
],
{ cwd: appPath }
);
server.stdout.on('data', (data) => {
console.log(`Server stdout: ${data}`);
});
server.stderr.on('data', (data) => {
console.error(`Server stderr: ${data}`);
});
server.on('close', (code) => {
console.log(`Server process exited with code ${code}`);
});
}
catch (err) {
dialog.showMessageBox(DialDesigner.main!, { title: 'Errore', message:
`PUBLIC: ${process.env.PUBLIC}
DIST: ${process.env.DIST}
EXE: ${join(appPath!, 'operations')}
`
});
app.quit();
}
}
private createWindow = () => {
const { width, height } = screen.getPrimaryDisplay().size;
DialDesigner.main = DialDesigner.newWindow({
title: 'Dial Designer',
width, height,
preload: join(__dirname, '../preload/index.js'),
});
if (DialDesigner.url) {
DialDesigner.main.loadURL(DialDesigner.url);
DialDesigner.main.webContents.openDevTools();
}
else {
DialDesigner.main.loadFile(DialDesigner.indexHtml);
}
DialDesigner.main.webContents.on('did-finish-load', () => {
DialDesigner.main?.webContents.send('main-process-message', new Date().toLocaleString())
});
// Make all links open with the browser, not with the application
DialDesigner.main.webContents.setWindowOpenHandler(({ url }) => {
if (url.startsWith('https:')) shell.openExternal(url)
return { action: 'deny' }
});
update(DialDesigner.main);
}
public initialize = () => {
try {
app.setPath('userData', `${app.getPath('appData')}/Dial Designer`);
app.whenReady()
.then(this.createWindow);
app.on('ready', this.runServer);
app.on('window-all-closed', () => {
DialDesigner.main = null
if (process.platform !== 'darwin') app.quit()
});
app.on('second-instance', () => {
if (DialDesigner.main) {
if (DialDesigner.main.isMinimized()) DialDesigner.main.restore();
DialDesigner.main.focus();
}
});
app.on('activate', () => {
const allWindows = BrowserWindow.getAllWindows()
if (allWindows.length) allWindows[0].focus();
else this.createWindow();
});
}
catch (err) {
dialog.showMessageBox(DialDesigner.main!, { title: 'Errore', message: `${(err as Error).stack}` });
app.quit();
}
}
public applicationMenu = (template: MenuItemConstructorOptions[]) => {
const menu = Menu.buildFromTemplate(template);
Menu.setApplicationMenu(menu);
}
}
1条答案
按热度按时间0s7z1bwu1#
我怀疑这是由于打包的路径与未打包的路径不同而导致的错误路径造成的。
追踪问题:
1.打开打包的应用程序目录并找到您的
app.asar
1.使用
npx @electron/asar extract app.asar appAsar
提取1.确保您的预加载脚本位于预期目录中-很可能由于打包而位于子目录中,并且您需要修补路径以调整应用程序是否打包
例如,在我们的代码中,我们使用这样的东西:
如果仍然不起作用-将
electron-unhandled
添加到您的应用程序中,方法是将这些行添加到您的main
和preload
进程脚本中。确保同时运行
npm install --save electron-unhandled
这将显示一个对话框,其中包含发生的错误(如果有)。