node监听系统进程?
发布于 19 天前 作者 liubin-webFront 1261 次浏览 来自 问答

我们用Electron开发的桌面应用,有个需求是离线编辑,把一个文件下载到本地用系统默认的编辑器打开它,在用户修改完关闭编辑器之后,把这个文件回传给服务端,现在我不知道怎么监听用户关闭编辑器这个事件???

10 回复

定时扫描文件是否有改动?

@im-here 文件改动事件可以监听到,可是回传是要在改动之后用户关闭编辑器进行的,如果编辑器没有关闭,就算文件改动了也不执行回传的,说明用户还有意向继续编辑

@liubin-webFront 那直接监听文件的修改时间试试。 如果用户用的编辑器不是自动保存的话,理论上用户在没有按下ctrl+s之前文件的修改时间应该都不会变的。只要检测到修改时间有变化就同步呗。

你这种不是用的你自己的编辑器,应该不可能做到用户关闭编辑器再回传。

参考百度网盘这种类似的,应该都是定时扫描+同步

可以试试这种方案: 使用child_process模块执行进程查询命令,window是tasklist,linux和mac是ps. 然后列一些支持的编辑器列表,从查询的列表中找出来再监听进程状态。当发生exit事件时发起你的业务代码逻辑

题外话: 你这种监听编辑器退出的方案是错误的,如果是我用命令通道>修改这个文件呢?最好是监听文件改变的方式。

简单点的,用户点关闭,弹窗确认,同时保存~、 或者直接弹个进度条,保存完自动关闭。

这个需求的方案的确是有问题的,类似于手机壁纸颜色要根据手机壳颜色变化。
调用系统的编辑器,就相当于另外的进程,和主程序就完全没有关系了,你要进行进程间通讯,而另外一个进程是不可编程的,基本上你只能让主程序做类似人类的操作,屏幕监听判断那显然不实际,那就剩监听任务管理器(进程列表),但是你以什么条件判断哪类进程的怎么样的变化作为触发“用户在结束了在这个编辑器上对该文件的编辑”界限是个问题。 大致上其实你只能通过进程名称(镜像名称),id和这类名称的进程的数量来判断,但是不同编辑器启动的进程是不一样的,有的很多有的可能1两个,并且启动过程中可能是变化的,加上如果系统本身就开有此类编辑器,有的编辑器编辑过程中插件等又可能会多出一些进程或关掉一些进程,规律可能是不同的,大大增加这个事件界定的难度,也就是耦合度非常高,你可能需要对不同操作系统不同编辑器的启动进程进行预先的规律判断,才有可能去实现这个逻辑,而且这个逻辑的可靠性可能是不确定的。
对于你这个需求,我特意对vscode进行了测试,假设是vscode,win上,当前没有打开任何vscode,可以在下载前获取code.exe进程列表,这时候应该是空的,记录下来,下载完成调用打开文件(假设默认就是启动了vscode,一个窗口),这时候会有差不多14个进程,当编辑完后这14个进程会全部不见,可以界定为触发了需求中的事件。另外是当系统已经打开过vscode,一个窗口,那么再打开一个窗口,完成后差不多会增加2个code.exe进程,那么逻辑可以是下载前同样检查一次,记录当前已经存在的code.exe进程的列表,编辑开始的时候记录另外一个列表,定时检查列表是否恢复到前一个状态,如果恢复了,可以界定触发了关闭编辑的。以下是简单的代码:

const cp = require('child_process');
const defaults = {
  cwd: __dirname,
  env: process.env
};
// 编辑前记录一次code.exe的tasklist列表
const checkTaskListCmd = 'tasklist /FI "IMAGENAME eq code.exe"';
// 这里处理命令行返回的应该需要更严谨一些,不过演示就这样先了
const pidReg = /\d{4,5}/g;
const beforeOpenTaskList = cp
  .execSync(checkTaskListCmd)
  .toString()
  .match(pidReg)
  .sort((a, b) => a - b);
const open = cp.spawn('explorer.exe', ['12312.txt'], defaults);

open.on('close', () => {
  console.log('已经打开了系统默认编辑器');
  const checkClose = setInterval(() => {
    const nowTaskList = cp
      .execSync(checkTaskListCmd)
      .toString()
      .match(pidReg)
      .sort((a, b) => a - b);
    if (nowTaskList.toString() === beforeOpenTaskList.toString()) {
      console.log('用户关闭了编辑');
      clearInterval(checkClose);
    }
  }, 1000);
});

然后想想,如果编辑过程中,用户又用其他vscode打开了一个新的窗口,那这个逻辑又有缺陷了,还得实际检测和标记具体是增加了哪个进程,判断要细到“哪些进程对应的就是需要触发的这个文件”

用 ffi 监听系统消息(user32.dll?) 过滤出文件关闭事件。不知道是否可行。

@ty4z2008 我说的监听编辑器退出应该和你说的监听进程状态是一个意思,本人是做web前端的,对window、Linus系统的一些概念不是太熟,描绘的不太专业哈。至于用什么方法去编辑,我在程序里写的是用户系统对此文件默认的编辑器,看用户电脑设置了,如果用户没有装任何编辑此文件的编辑器,就和windows上打开一个没有编辑器文件的显示一样。谢谢你的回复,我会撸一遍的。

@HobaiRiku 谢谢你的耐心解答。我们做的产品是类似于云盘,对于云盘上的文件可以有在线编辑、和离线编辑,在线编辑就是我们软件里集成的一些编辑器,离线编辑就是把这个文件下载到本地,用本地默认编辑器编辑完回传再删掉本地的,在程序里我能知道的信息就是这个文件的id、名称、格式、文件下载的位置,至于用户能不能打得开,用什么编辑器打开,我是不知道的,或者换一种思路,在windows上打开一个文件,这个文件就会被一个进程占用,比如这时候删除这个文件是删不掉的, 如果在进程改变的时候同时判断这个文件有没有被进程占用,是不是就知道这个文件有没有还被编辑器打开呢。

@liubin-webFront 不同编辑器的逻辑是不一样的,比如目前大部分的编辑器一般都是缓存起来,你打开文件后源文件可以随便删除,而又比如excel这种,不管你打开多少个excel,都只有一个进程,想统一起来我感觉还是有点难。

回到顶部