【Electron-vue】构建桌面应用(7)-nodejs执行exe程序并获取输出值

1.前言

在之前的文章中,实现了Electron-vue在不同系统打包成安装程序。但这只是前端build/package之后的文件打包,虽然服务端的编译之后的exe文件也可以放到一起打包,并且可以去启动服务端程序。然而不能与服务端通信的话,那么这个程序存在的意义就不大。所以在这片文章中会讲一下怎么在安装之后,启动应用程序调用服务端程序,同时获取服务端的输出值/返回值。

由于不是传统意义上的前后端通信(常见的前后端通信,只需要使用http/https进行通信即可,request发送请求,response返回请求结果,然后解析一顿操作即可),然而当服务端打成exe可执行文件时,就需要使用command去通信,同时需要借助进程之间的通信方式来处理。

2.nodejs实现exe调用

2.1主进程-子进程-渲染进程

我们知道在现在的前端项目构建中,尤其是工程化的项目创建,都会依赖nodejs,而nodejs本身也足够强大提供一些常用的方法来为js服务。而在我们的Electron-vue项目中,也是需要使用nodejs提供的一些服务去实现进程之间的通信。

在这里,主要分为主进程,子进程和渲染进程。

主进程与子进程之间的通信(也就是exe的调用和执行),使用的是nodejs提供的child_process实现。而主进程和渲染进程之间的通信使用的是electron中的BrowserWindow来实现。

主要的逻辑处理是:

  1. 主进程通过nodejs提供的child_process来实现启动子进程,并且获取子进程的输出值
  2. 主进程获取子进程输出值,将输出值传给渲染进程
  3. 渲染进程获取到主进程的数据值,将其呈现在页面上,比如子进程是否启动成功等

2.2主进程启动子进程

主进程启动子进程可借助于nodejschild_process提供的方法。
child_process提供了七中方式去创建子进程

异步方式

  1. child_process.exec(command[, options][, callback])
  2. child_process.execFile(file[, args][, options][, callback])
  3. child_process.fork(modulePath[, args][, options])
  4. child_process.spawn(command[, args][, options])

同步方式

  1. child_process.execFileSync(file[, args][, options])
  2. child_process.execSync(command[, options])
  3. child_process.spawnSync(command[, args][, options])

我们知道同步方式会导致进程阻塞,所以我们一般会使用异步进程的方式去处理。

从命令的方式也可以看出其中execspawn的参数是command也就是命令行的形式去执行,而我的需求也是使用命令行启动一个exe文件基本上是start xxx.exe。所以在这里也只讲一下execspawn

从官方的文档可以看得出,spawn是最基本的,而exec是对于spawn的一种封装或者说是扩展,意思是说spawn会基于命令command直接执行,而exec会衍生 shell,然后在 shell 中执行 command,并缓冲任何产生的输出。 传给 exec函数的 command 字符串会被 shell 直接处理,特殊字符(因 shell 而异)需要被相应地处理

2.2.1 exec执行exe文件

child_process.exec(command[, options][, callback])

上面的一些参数可以参考exec command。在这里我只强调两个属性值,那就是timeoutmaxBuffer

为什么要强调这个属性呢?是因为我在使用exec执行命令的时候,exe文件可以执行,但是无论如何怎么都进不去callback函数,除非你设置timeout参数不为0

为了开发方便便于debug主程序的运行,借助于electron-log输出主程序的日志文件,以便定位执行exe程序时是否有输出返回值。

1、配置日志文件
安装electron-log,因为日志只是为了方便我们在开发环境下做问题定位,所以,需要开发依赖,而不是生产依赖。

npm install electron-log --save-dev

2、在main/index.js中配置日志

import log from 'electron-log'
//配置输出路径,这里为了方便我就直接输出到开发项目根目录下
log.transports.file.file = "D://my-project/agent.log";

3、创建exec方法
main/index.js文件中创建执行程序的方法

const cp = require('child_process')
function execPrograme() {
   
  log.info("开始执行-----------------------------")
  cp.exec(`start ${
     __dirname}/main.exe`,(error, stdout, stderr) => {
   
    if (error) {
   
      log.error(`执行的错误: ${
     error}`);
      return;
    }
    log.info(`stdout: ${
     stdout}`);
    log.error(`stderr: ${
     stderr}`);
  })
  log.info("结束执行-----------------------------")
}

然后观察一下控制台会发现vc code终端输出的数据仅有开始和结束的输出,而没有callback中的输出,得不到我想要的exe执行结果。
在这里插入图片描述
而在日志文件中也可以看到:
在这里插入图片描述
这个问题我搜了半天一直在关注为什么exec命令为什么走不进去callback函数中,在网上找到一大堆方法,结果没有可行的,后来还是在官网api上找到了解决办法:

timeout 默认值: 0。
为0是什么意思呢?官网没有给出解释,而是给出了大于0的时候的解释
如果 timeout 大于 0,则当子进程运行时间超过 timeout 毫秒时,父进程会发送由 killSignal 属性(默认为 ‘SIGTERM’)标识的信号

看了看上面的解释,似乎还是没明白。大于0会发出killSignal的信号,这个意思难道就是杀死进程?为0的话进程就一直在执行,导致没法进入到callback回调函数中。

那如果我设置一个大于0的值呢?

function execPrograme() {
   
  log.info("开始执行-----------------------------")
  cp.exec(`start ${
     __dirname}/main.exe`,
  • 4
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值