这个问题涉及到很多知识,而且要想把这个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使用者指定的图标(这是有解决办法的);

如何把Electron做成一个Runtime,让多个应用共享同一个Electron的更多相关文章

  1. 如何将打包好的文件做成一个APP

    本文主要是用来简短的对做成一个APP进行说明,内容可能不是多详细,但会给出具体思路.(仅供参考) 因为各种打包和生成APP的方式多样,今天这里仅仅对用Hbuilder打包进行说明. 1.首先当然需要一 ...

  2. 跟我一起使用electron搭建一个文件浏览器应用吧(四)

    在软件的世界里面,创建一个新项目很容易,但是坚持将他们开发完成并发布却并非易事.分发软件就是一个分水岭, 分水岭的一边是那些完成的被全世界用户在用的软件,而另外一边则是启动了无数项目却没有一个完成的. ...

  3. 使用electron开发一个h5的客户端应用创建http服务模拟后台接口mock

    使用electron开发一个h5的客户端应用创建http服务模拟后端接口mock 在上一篇<electron快速开始>里讲述了如何快速的开始一个electron的应用程序,既然electr ...

  4. electron教程(番外篇二): 使用TypeScript版本的electron, VSCode调试TypeScript, TS版本的ESLint

    我的electron教程系列 electron教程(一): electron的安装和项目的创建 electron教程(番外篇一): 开发环境及插件, VSCode调试, ESLint + Google ...

  5. win7问题解决,凭据管理器和无法访问,不允许一个用户使用一个以上用户名与服务器或共享资源进行多重连接。

    WIN7凭据管理器,如果你用一个帐号远程登录以后在电脑中会记住这个信息,假如你想用另外的帐号,那么就到控制面板-凭据管理器里中进行修改或者删除. 如果你登录以后提示,“无法访问.不允许一个用户使用一个 ...

  6. JAVA调用系统命令或可执行程序--返回一个Runtime运行时对象,然后启动另外一个进程来执行命令

    通过 java.lang.Runtime 类可以方便的调用操作系统命令,或者一个可执行程序,下面的小例子我在windows和linux分别测试过,都通过.基本原理是,首先通过 Runtime.getR ...

  7. 把linux可执行程序做成一个服务[转]

    转自:http://www.2cto.com/os/201202/121249.html 在linux系统启动的时候,我们可以看到很多服务性程序一个接一个的被启动(就是那些后面有一个兰色[OK]的行) ...

  8. Jquery 类似新浪微博,鼠标移到头像,用浮动窗口显示用户信息,已做成一个jquery插件

    请注意!!!!! 该插件demo PHP 的 demo下载  C#.NET的demo下载 需要如下图, 1.鼠标移动到头像DIV时,Ajax获取数据,并让浮动DIV显示出来. 2.鼠标可以移动到上面浮 ...

  9. Electron 创建一个空白的界面

    添加应用 首先添加一个Lorikeet版本的Electron应用. 'use strict' const electron = require('electron'); const app = ele ...

随机推荐

  1. [NOIP2017 提高组] 列队

    考虑我们需要维护的是这样一个东西. 即可能变化的只有每一行前\(m - 1\)个,和最后一列. 我们考虑对每一行开一个权值线段树,记录原本序列的第\(x\)个是否被一出,且用一个\(vector\)记 ...

  2. [Linux] Miniconda安装及其使用

    集群环境下安装conda进行软件管理.Miniconda是Anaconda的简化版,对于一般需求而言就够用了.因此,我这里安装Minconda3进行软件安装管理. 安装 Miniconda下载地址,版 ...

  3. Glib 对 C 函数进行单元测试

    1. Glib 单元测试框架 Glib 为单元测试提供了一套完整的测试框架,每个测试运行包括以下几个部分 测试数据结构 测试 setup 与 teardown 函数 测试函数 2. 单元测试数据结构 ...

  4. Shell 变量嵌套

    实现:eval 1 a="indv1" 2 indv1="Sus1" 3 4 eval tmp='$'$a 5 echo $tmp //这里 echo 返回值为 ...

  5. ubuntu20.04安装EasyConnect兼容性问题解决

    目录 1. 命令行启动EasyConnect 2. 降级pango 3. 重新启动EasyConnect,即可成功启动 Ubuntu20.04安装EasyConnect后无法启动的解决方案 工作使用操 ...

  6. chmod文件权限分配问题

    一. 文件(文件夹)的权限问题 一个文件或者文件夹,使用它的人有三类:root.当前用户和其他用户,例如,我们可以通过 ls -l xxx.xxx 来查看文件 "xxx.xxx" ...

  7. 前端3 — js — BOM没完( 不了解也行 )

    1.js是什么? -- 英文全称javascript javaScript(简称"JS") 是一种具有函数优先的轻量级,解释型或即时编译型的编程语言.虽然它是作为开发Web页面的脚 ...

  8. Applescript快速入门及OmniFocus每日md报告开发

    本篇主要记录 Applescript 基础语法,以及利用 applescript 生成 omnifocus 每日报告 从 windows 转换到 macos,最近一直在不断折腾,这两天浏览 githu ...

  9. 看动画学算法之:二叉搜索树BST

    目录 简介 BST的基本性质 BST的构建 BST的搜索 BST的插入 BST的删除 简介 树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的非线性的数据结构. 树是由很多个节点组 ...

  10. 100个Shell脚本——【脚本7】批量建立用户

    [脚本7]批量建立用户 编写shell脚本,批量建立用户user_00, user_01, ... user_100并且所有用户同属于users组. 一.脚本 #!/bin/bash group=`c ...