惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

D
Docker
博客园 - 三生石上(FineUI控件)
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园_首页
Microsoft Azure Blog
Microsoft Azure Blog
GbyAI
GbyAI
腾讯CDC
酷 壳 – CoolShell
酷 壳 – CoolShell
M
MIT News - Artificial intelligence
Stack Overflow Blog
Stack Overflow Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
Jina AI
Jina AI
爱范儿
爱范儿
博客园 - 【当耐特】
雷峰网
雷峰网
S
SegmentFault 最新的问题
美团技术团队
Blog — PlanetScale
Blog — PlanetScale
The GitHub Blog
The GitHub Blog
有赞技术团队
有赞技术团队
G
Google Developers Blog
大猫的无限游戏
大猫的无限游戏
Google DeepMind News
Google DeepMind News
J
Java Code Geeks

博客园 - liulun

开源自荐:功能齐全的截图软件(仅1M) 开源自荐:功能齐全的截图工具(含录屏、截长图,体积仅780KB) 自荐:开源截图工具ScreenCapture:超多控制指令,支持截长图 脚踏esbuild祥云,胸怀tsx利刃,身披scss羽衣,追寻前端的本质 开源项目自荐:截图工具(小、快、功能丰富) 如何开发Vite3插件构建Electron开发环境 Electron是什么以及可以做什么 线上Electron应用具备哪些特征? 桌面软件开发框架大赏 微软要放弃Electron了???聊聊WebView2 自己实现一个Electron跨进程消息组件(兼新书自荐) 一个Electron的设计缺陷及应对方案 如何点击穿透Electron不规则窗体的透明区域 Electron团队为什么要干掉remote模块 谈Vite在Electron环境下吃花卷拉馒头的现象 公司只提供签名服务,不提供证书文件,如何打包Electron应用 vue3微前端架构——基于蚂蚁qiankun框架 Vite ❤ Electron——基于Vite搭建Electron+Vue3的开发环境【一】 Electron安装过程深入解析(读完此文解决Electron安装失败导致的无法启动,无法打包的问题) 大型Electron应用本地数据库技术选型 极客手中的利器Electron
如何把Electron做成一个Runtime,让多个应用共享同一个Electron
liulun · 2021-12-24 · via 博客园 - liulun

这个问题涉及到很多知识,而且要想把这个Runtime做好很绕。

下面我就说一下我的思路:
(以下内容以Windows平台为基础,Mac平台和Linux平台还得去调查一下,才能确定是否可行)

首先,我们先区分三类用户:

  1. Runtime建设者(就是我们)
  2. Runtime使用者(就是使用Runtime的开发者)
  3. 最终用户(就是使用Runtime开发者开发的应用的那些用户)

接下来我们就以Runtime建设者的视角来审视这项工作

首先我们要为Runtime使用者提供一个专有的打包工具,我们就叫它:打包工具。这个打包工具还内置了几个可执行程序,我们给他们起个名字,分别叫:

  • 最终安装程序
  • 最终执行程序
  • 最终卸载程序

好,我们一个一个聊他们的职责

打包工具的职责
按Runtime使用者的要求修改最终执行程序的图标、应用签名、版本、版权、文件名等资源信息;
按Runtime使用者的要求修改最终卸载程序的图标、应用签名、版本、版权、文件名等资源信息;
把最终执行程序、最终卸载程序与Runtime使用者开发好的HTML/CSS/JS等静态文件放到一起,压缩成一个压缩包,我们叫他:资源文件
把这个资源文件以资源的形式封装到最终安装程序中;
按Runtime使用者的要求修改这个最终安装程序的图标、应用签名、版本、版权、文件名等资源信息;
(修改资源的代码,后文有介绍)

这几个工作完成之后,Runtime使用者就可以把这个最终安装程序分发给最终用户了。

最终安装程序的职责
这个最终安装程序在最终用户的电脑上运行时,会完成以下工作:

检查最终用户的注册表,看其是否安装了我们的Electron Runtime
如果没有安装,则下载Electron的发行版,释放到一个特定目录下,并在注册表记下来。
在这个特定目录下记录当前应用的信息(卸载当前应用时要用到);
把自身的资源释放到最终用户指定的目录内,也就是前文说的资源文件
解压缩资源文件得到最终执行程序、最终卸载程序和Runtime使用者开发的HTML/CSS/JS等静态文件
写注册表记录最终卸载程序的位置,这样用户就可以在控制面板里卸载我们的程序了。
按最终用户的要求,创建开始菜单图标、桌面图标,这些图标均指向最终执行程序
(读取资源的代码,后文有介绍)

如果最终用户工作在没有网络的环境下,那么我们也可以允许Runtime使用者把Electron Runtime打包到最终安装程序内,这是打包工具的职责。

如果担心Electron官方提供的下载地址速度慢,可以考虑使用国内镜像地址:​npmmirror.com/mirrors/electron/

最终执行程序的职责
检查用户注册表,找到Electron Runtime的放置路径
启动Electron Runtime并把当前应用的入口程序当做参数传给Electron.exe,应用入口程序就是Runtime使用者开发HTML/CSS/JS等静态文件之一,
electron.exe path/to/entry.js
最终卸载程序的职责
删除安装目录下的文件
删除注册表的卸载程序信息
删除Electron Runtime所在目录下的应用程序信息,如果发现没有别的应用在依赖Electron Runtime了,那么就把Electron Runtime所在目录也删掉。


把一个文件作为资源写入一个可执行程序的代码如下所示:

HANDLE hFile;
DWORD dwFileSize,dwBytesRead;
LPBYTE lpBuffer;
char szFile[MAX_PATH+1] = {0};
::GetDlgItemText(hwnd,EditId,szFile,MAX_PATH);
hFile = CreateFile(szFile,GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
dwFileSize = GetFileSize(hFile, NULL);
lpBuffer = new BYTE[dwFileSize];
ReadFile(hFile, lpBuffer, dwFileSize, &dwBytesRead, NULL);
HANDLE hResource = BeginUpdateResource(szFilePath, FALSE);
UpdateResource(hResource,RT_RCDATA,MAKEINTRESOURCE(EditId),MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),(LPVOID)lpBuffer,dwFileSize);
EndUpdateResource(hResource, FALSE);
delete [] lpBuffer;
CloseHandle(hFile);
return 1;

可执行程序读取自身资源,把资源写到指定路径下的代码如下:

HMODULE hInstance = ::GetModuleHandle(NULL);
TCHAR szFilePath[MAX_PATH + 1];
GetPath(szFilePath,resourceName,hInstance);
HRSRC hResID = ::FindResource(hInstance,resourceID,RT_RCDATA);
HGLOBAL hRes = ::LoadResource(hInstance,hResID);
LPVOID pRes = ::LockResource(hRes);
DWORD dwResSize = ::SizeofResource(hInstance,hResID);
if(!dwResSize) return 0;
HANDLE hResFile = CreateFile(szFilePath,GENERIC_WRITE,0,NULL,CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);
DWORD dwWritten = 0;
WriteFile(hResFile,pRes,dwResSize,&dwWritten,NULL);
CloseHandle(hResFile);
if(dwResSize == dwWritten) return 1;
return 0;

这两段代码是从我的一个项目中摘抄出来的,仅供参考。

遗留的问题
我们并没有考虑多Electron版本共存的问题;
此方案高度依赖Windows API,跨平台实现差异肯定会比较大;
应用程序启动后,任务栏的图标是Electron Runtime的图标,而非Runtime使用者指定的图标(这是有解决办法的);