@@ -25,6 +25,7 @@ class ElectronApp {
2525 mountAppEvents ( ) : void {
2626 // 本程序是启动的第二个实例时,将因获不到锁而退出
2727 if ( ! app . requestSingleInstanceLock ( ) ) {
28+ console . log ( 'FFBox 已启动,暂不支持启动第二个实例' ) ;
2829 app . quit ( ) ;
2930 process . exit ( 0 ) ;
3031 }
@@ -51,6 +52,13 @@ class ElectronApp {
5152 this . createMainWindow ( ) ;
5253 }
5354 } ) ;
55+ app . on ( 'window-all-closed' , ( ) => {
56+ // FFBoxService 进程尽管没有指定 detached
57+ // 但在 macOS 上,主进程退出不会导致 service 退出;在 linux 上,主进程调用了 app.exit() 之后依然会等待 service 退出
58+ // 故保险起见主动关闭
59+ this . service ?. sendSig ( 9 ) ;
60+ app . exit ( ) ;
61+ } ) ;
5462
5563 // Set app user model id for windows
5664 // electronApp.setAppUserModelId('com.electron');
@@ -160,11 +168,42 @@ class ElectronApp {
160168 // this.electronStore = new ElectronStore();
161169 }
162170
163- createService ( ) : Promise < void > {
171+ async createService ( ) : Promise < void > {
164172 this . service = new ProcessInstance ( ) ;
165173 // 目前做不了进程分离,因为启动的时候会瞬间弹一个黑框,十分不优雅。等后期给选项让用户决定行为再去做:https://github.com/nodejs/node/issues/21825
166174 // return this.service.start('FFBoxService.exe', [], { detached: true, stdio: 'ignore', windowsHide: true, shell: false });
167- return this . service . start ( getOs ( ) === 'Windows' ? 'FFBoxService.exe' : path . join ( process . resourcesPath , 'FFBoxService' ) ) . then ( ( ) => osBridge . sendLoadStatus ( 'service' ) ) ;
175+ let servicePath = '' ;
176+ if ( getOs ( ) === 'Windows' ) {
177+ servicePath = 'FFBoxService.exe' ;
178+ } else if ( getOs ( ) === 'MacOS' ) {
179+ servicePath = path . join ( process . resourcesPath , 'FFBoxService' ) ;
180+ } else if ( getOs ( ) === 'Linux' ) {
181+ // this.mainWindow.webContents.send('debugMessage', 'service 路径', process.execPath, __dirname, __filename, process.cwd(), path.join(process.execPath, '../FFBoxService'));
182+ await fs . access ( './FFBoxService' , fs . constants . X_OK ) . then ( ( result ) => {
183+ servicePath = './FFBoxService' ; // 通过终端直接执行
184+ } ) . catch ( ( ) => { } ) ;
185+ await fs . access ( path . join ( process . cwd ( ) , 'FFBoxService' ) , fs . constants . X_OK ) . then ( ( result ) => {
186+ servicePath = path . join ( process . cwd ( ) , 'FFBoxService' ) ; // 无沙箱双击执行、通过终端直接执行
187+ } ) . catch ( ( ) => { } ) ;
188+ await fs . access ( path . join ( process . execPath , '../FFBoxService' ) , fs . constants . X_OK ) . then ( ( result ) => {
189+ servicePath = path . join ( process . execPath , '../FFBoxService' ) ; // AppImage 双击执行(/tmp 目录)、deb 安装后双击执行(/opt/FFBox/)
190+ } ) ;
191+ }
192+ // this.mainWindow.webContents.send('debugMessage', '选出路径', servicePath);
193+ return new Promise ( ( resolve , reject ) => {
194+ this . service . start ( servicePath ) . then ( ( ) => {
195+ // 需要加一点延迟才报告成功,主要是因为 service 启动 server 需要一定时间,待 server 启动好之后才让 renderer 去连接
196+ // 在 Windows 中可能不需要加这个延时,但是在 macOS 和 Linux 上似乎都是需要的
197+ // 另外,调试过程中发现,如果尝试使用 debugMessage 把调试消息发送给 renderer,当程序忙的时候 renderer 并不一定会按实际顺序去显示,因此需要适当增加延时以验证 Promise 正常工作
198+ // 150ms 延迟在 Linux 上很可能不够。但目前的设计是在 renderer 那边自动重试,主进程尽快报告完成。
199+ setTimeout ( ( ) => {
200+ osBridge . sendLoadStatus ( 'service' ) ;
201+ resolve ( undefined ) ;
202+ } , 150 ) ;
203+ } ) . catch ( ( ) => {
204+ reject ( ) ;
205+ } ) ;
206+ } ) ;
168207 }
169208
170209 mountIpcEvents ( ) : void {
@@ -251,9 +290,7 @@ class ElectronApp {
251290 } ) ;
252291
253292 // 启动一个 ffboxService,这个 ffboxService 目前钦定监听 localhost:33269,而 serviceBridge 会连接此 service
254- ipcMain . on ( 'startService' , ( ) => {
255- this . createService ( ) ;
256- } ) ;
293+ ipcMain . handle ( 'startService' , ( ) => this . createService ( ) ) ;
257294
258295 // osBridge 系列
259296 ipcMain . on ( 'triggerSystemMenu' , ( ) => osBridge . triggerSystemMenu ( ) ) ;
0 commit comments