acking-you / windowsapp_singleton

For many times to open only reuse the same process.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

windowsapp_singleton

这是一个我在开发桌面端程序(NoteWithCards)的时候用C++写的一个插件,开发和联调使用的时候经历了太多曲折. 如果有兴趣可以了解下我经历了什么: 总结

实现背景

为什么要有这个插件,他能干什么?

为了实现在桌面端多次打开应用程序最终只启动一个进程,并且后续打开的行为会把该进程的窗口立即放入前台显示,具体用法可以查看后续描述的API.

文件说明

比较关键的几个文件:

  • cmake/dll_support.cmake : 提供 dll_support cmake函数,该函数接收多个 targettarget 完成构建之后,将主项目产生的库文件拷贝到参数对应的 target 产生的文件夹中(主要是为了让Windows平台的dll库可以正常的被可执行文件加载,其他平台则不需要这个多余的操作,具体原因可以看总结).
  • src/pub.h : 所有对外开放的API.
  • src/impl.cc : 具体实现.
  • tests/show_window_main.cc : 可执行程序脚本的实现.

具体使用

暂时只支持Windows系统,后续如果有需求会考虑增加更多平台.

API

所有API在 pub.h 文件中.

  • getpid:获取当前进程id.
  • exist_pid:根据进程id判断该进程是否存在.
  • exist_pid_with_title:根据进程id和该窗口的title判断对应的进程是否存在.
  • show_window:根据进程id和title找到对应的窗口并放入前台显示.

如何使用

库的使用

关于库的使用,我已经打包好了对应的 dll 链接库,如果有需要可以在release页面自取. 任意其他高级语言想要调用这些写好的接口,只需要打开链接库,然后查询对应的函数符号,即可完成对任意语言调用的绑定.(如java的JNI或dart的ffi)

发布页面中还有一个可执行程序 windowsapp_singleton_main.exe 该程序在运行的时候需要传入两个参数进程 id 和需要打开的窗口 title ,如果窗口存在,他会帮你打开该窗口到前台展示,该程序一般作为脚本嵌入其他程序.

如何实现最终的效果

如果要实现对某个桌面端程序只启一个进程,并且后续打开的行为会把该进程的窗口立即放入前台显示. 步骤如下:

  1. 你可以在桌面端程序启动的时候保存当前进程的id到某个文件中.
  2. 每次启动从那个文件中获取该进程id,通过调用本插件的接口来查询当前进程是否存在.
  3. 如果进程存在那么根据进程id和需要显示的窗口title来把那个窗口显示出来(推荐使用 windowsapp_singleton_main.exe 来完成),并把当前需要启动的进程结束.
  4. 如果进程不存在那么就正常当前进程.

思考:上述实现存在什么问题?

虽然直接存进程id来判断当前是否有该id的进程存在是较为优秀的做法,它能够避免存储状态字(用于标记程序是否已经启动)所导致的一些问题,比如突然断电,程序无法正常退出,状态字无法正确的更新,这将会导致后续的程序永远无法启动. 直接存进程id就避免了这样的问题,但是如果进程id对应的目标程序结束后,有其他无关进程占用了该id,那么也是会导致类似的问题,虽然这很难发生.这种情况其实也是可以进一步优化的,比如调用 exist_pid_with_title 来判断目标进程是否存在,这个 api 通过两个参数来决定唯一性,进程id和该进程的窗口title,所以算是完全解决了这个问题.

About

For many times to open only reuse the same process.


Languages

Language:CMake 46.6%Language:C++ 45.7%Language:C 7.7%