Electron 快速入门


=Start=

缘由:

学习了解一下Electron是什么,能做什么,代码该怎么写,方便以后参考。

正文:

参考解答:
1、Electron是什么?

Electron是由Github开发,用HTML,CSS和JavaScript来构建跨平台桌面应用程序的一个开源库。Electron通过将ChromiumNode.js合并到同一个运行时环境中,并将其打包为Mac,Windows和Linux系统下的应用来实现这一目的。

2、Electron能做什么?

Electron 可以让你使用纯 JavaScript 调用丰富的原生(操作系统) APIs 来创造桌面应用。你可以把它看作一个 Node. js 的变体,它专注于桌面应用而不是 Web 服务器端。

这不意味着 Electron 是某个图形用户界面(GUI)库的 JavaScript 版本。 相反,Electron 使用 web 页面作为它的 GUI,所以你能把它看作成一个被 JavaScript 控制的,精简版的 Chromium 浏览器。

3、Electron应用的开发

①开发环境准备

# 下面这行的命令会打印出Node.js的版本信息
node -v

# 下面这行的命令会打印出npm的版本信息
npm -v

# 全局安装 electron 然后查看其版本
npm install electron@latest -g
electron --version

②代码目录结构

从开发的角度来看, Electron application 本质上是一个 Node. js 应用程序。 与 Node.js 模块相同,应用的入口是 package.json 文件。一个最基本的 Electron 应用一般来说会有如下的目录结构:

your-app/
├── package.json
├── main.js
└── index.html

③Demo应用开发

为你的新Electron应用创建一个新的空文件夹。 打开你的命令行工具,然后在该文件夹下运行npm init命令:

npm init

该 npm init 命令会帮助你创建一个基本的 package.json 文件。其中的 main 字段所表示的脚本为应用的启动脚本,它将会在主进程中执行。 如下片段是一个 package.json 的示例:

{
"name": "your-app",
"version": "0.1.0",
"main": "main.js"
}

下面是一个简单的main.js文件,它将在应用程序准备就绪后打开一个窗口,同时打开开发者工具,并添加上处理窗口关闭事件、在macOS用户点击dock上图标时重建窗口的逻辑:

const { app, BrowserWindow } = require('electron')

// 保持对window对象的全局引用,如果不这么做的话,当JavaScript对象被
// 垃圾回收的时候,window对象将会自动的关闭
let win

function createWindow () {
// 创建浏览器窗口。
win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true
}
})

// 加载index.html文件
win.loadFile('index.html')

// 打开开发者工具
win.webContents.openDevTools()

// 当 window 被关闭,这个事件会被触发。
win.on('closed', () => {
// 取消引用 window 对象,如果你的应用支持多窗口的话,
// 通常会把多个 window 对象存放在一个数组里面,
// 与此同时,你应该删除相应的元素。
win = null
})
}

// Electron 会在初始化后并准备
// 创建浏览器窗口时,调用这个函数。
// 部分 API 在 ready 事件触发后才能使用。
app.on('ready', createWindow)

// 当全部窗口关闭时退出。
app.on('window-all-closed', () => {
// 在 macOS 上,除非用户用 Cmd + Q 确定地退出,
// 否则绝大部分应用及其菜单栏会保持激活。
if (process.platform !== 'darwin') {
app.quit()
}
})

app.on('activate', () => {
// 在macOS上,当单击dock图标并且没有其他窗口打开时,
// 通常在应用程序中重新创建一个窗口。
if (win === null) {
createWindow()
}
})

// 在这个文件中,你可以续写应用剩下主进程代码。
// 也可以拆分成几个文件,然后用 require 导入。

然后,创建你想展示的 index.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Hello World!</title>
</head>
<body>
<h1>Hello World!</h1>
We are using node <script>document.write(process.versions.node)</script>,
Chrome <script>document.write(process.versions.chrome)</script>,
and Electron <script>document.write(process.versions.electron)</script>.
</body>
</html>

在创建并初始化完成 main.js、 index.htmlpackage.json之后,您就可以在当前工程的根目录执行 npm start 命令来启动刚刚编写好的Electron程序了。


一些简单的知识点和注意事项:

主进程&渲染进程
  • 在 Electron 里,运行 package.json 里 main 脚本的进程被称为主进程
  • 由于 Electron 使用 Chromium 来展示页面,所以 Chromium 的多进程结构也被充分利用。每个 Electron 的页面都在运行着自己的进程,这样的进程我们称之为渲染进程。在一般浏览器中,网页通常会在沙盒环境下运行,并且不允许访问原生资源。然而,Electron 用户拥有在网页中调用 io.js 的 APIs 的能力,可以与底层操作系统直接交互。
主进程和渲染进程的区别

主进程使用 BrowserWindow 实例创建网页。每个 BrowserWindow 实例都在自己的渲染进程里运行着一个网页。当一个 BrowserWindow 实例被销毁后,相应的渲染进程也会被终止。

主进程管理所有页面和与之对应的渲染进程。每个渲染进程都是相互独立的,并且只关心他们自己的网页。

由于在网页里管理原生 GUI 资源是非常危险而且容易造成资源泄露,所以在网页面调用 GUI 相关的 APIs 是不被允许的。如果你想在网页里使用 GUI 操作,其对应的渲染进程必须与主进程进行通讯,请求主进程进行相关的 GUI 操作。

在 Electron,我们提供用于在主进程与渲染进程之间通讯的 ipc 模块。并且也有一个远程进程调用风格的通讯模块 remote

低版本Electron不支持loadFile

1.x2.xelectron中,如果要使用loadFile函数,就会报错unknown function。所以如果想用这个函数的话,需要更新到 3.x 及以后版本的 Electron 。

参考链接:

=END=

,

《“Electron 快速入门”》 有 10 条评论

  1. 用Nodejs开发桌面应用。NW.js 和 Electron 各有什么优缺点,你选择哪个?
    https://www.zhihu.com/question/38854224
    `
    我们最近有个项目需要使用Node桌面版技术,正如大多数人一样,我的初次选型是NW,那么出乎意料,大坑来了!!!

    倘若你的桌面版应用没有跟底层(C++模块)挂钩,也就是没有使用到消息推送、版本升级、打印功能之类的东西,但是bug还是挺多的。并且一旦使用到这些功能,你就彻底调到坑里了,nw有个致命的缺陷在于所有的非javascript编写的模块都需要重新用nw-gyp重新编译一下,这个编译的过程会出现各种各样的问题。而Electron几乎可以使用所有的node模块,只需要node-gyp编译的即可。主要深坑就在这!!!还有,NW不像Electron自带版本升级。

    nw唯一的好处是啥?兼容window XP呗。
    `
    http://tangiblejs.com/posts/nw-js-electron-compared

  2. 怎么去阅读Chromium的源码?
    https://www.zhihu.com/question/306408034/answer/565791530
    `
    从初学者角度的话,如果是刚开始研究chromium,建议找个老版本chromium来看。新版太大太复杂了。我建议从github搜下 chromium.bb 这个项目,是个chromium49的删减版。之所以推荐这个,有几个原因:

    0,工程环境比原版chromium好搭多了,不用翻墙,不用改一些系统设置。90%的初学者我估计卡在搭chromium环境这了,尤其是国内。。
    1,代码量相对较小,所以直接可以生成vs工程后配合vax的代码着色和智能跳转阅读。有VAX辅助,对于查找函数具体位置有很大帮助。
    2,同样由于代码量小,你可以用vs直接编译跑起来。阅读chromium代码你一定要调试,否则很难理清某个流程。

    搭好环境后,建议你疯狂搜下网上讲解chromium架构的文章预热一下。否则你会不知所云。先把chromium的进程架构了解下,大概每个进程是做什么的,然后开始研究content层,这是chromium最主要的层,负责连接所有其他组件。

    其他具体架构细节以后想到再写……
    `
    Chromium
    https://www.zhihu.com/topic/19557071/top-answers

  3. 向Typora学习electron安全攻防
    https://mp.weixin.qq.com/s/Ggx34AqhzsbBLkecv5RNJw
    `
    越来越多的应用开始使用 electron 来构建跨平台桌面应用。从实现方式上来说,其本质还是基于chrome内核的html、js、css构成的应用,基于浏览器,代码必定会暴露在用户侧,任何加密手段只是增加破解门槛跟时间成本而已。

    # 认识electron项目文件目录特征
    electron打包的项目,最常见的就是 asar 格式的私有编码文件,里面包含文件名、大小、内容偏移量等数据,按文件头部的 json内容 解析即可提取出所有文件。

    # electron asar解包
    目前来说,官方的版本并没有提供保护源码的方法。在github开源的找到个大神提供的解决方案(https://github.com/toyobayashi/electron-asar-encrypt-demo) ,该方案可以把启动文件编译为node二进制文件,作为启动入口,来保护薄弱的js代码。在项目启动时,将加密后的代码进行解密,交回electron流程进行执行,从而避免上述步骤直接解包拿到源代码的可能。

    经过分析对比,typora用的恰好是这个demo提供的思路。

    找到上述步骤解压成功的 package.json 文件,main属性就是 electron 项目启动的主入口。把 main.node 拖到ida中, 分析执行流程。

    结合 electron-asar-encrypt-demo 跟 IDA伪代码, 可以定位到两个关键函数 napi_create_string_utf8 跟 napi_call_function。

    # 万能js提取方案

    已知经过编译后的node文件, 在执行前,都会调用 napi_create_string_utf8 创建js字符串,所以在调用该函数的时候,基于electron没有自带加密的特性,想要运行js流程,必定会传递明文,所以在加载流程上截断,就可以导出解密后的数据。

    解包项目中的所有 asar文件,就能拿到所有的源代码,并且把解压的文件夹,改成对应的 asar 文件名即可正常运行项目,无需重打包即可调试。

    # 无限试用思路

    删除注册表键,让程序认为是第一次安装。

    # 去除授权功能实现单机版本思路

    将所有的网络验证给他删掉/注释掉, 也可以直接把 “是否授权” 的变量,改成true即可。

    # 注册机思路

    由于该示例使用了rsa解密,所以要基于官方版本编写注册机就不太行了。一定要出注册机的话,需要先替换截图部分的rsa公钥即可。

    # 自建授权网关实现注册机思路

    自建网关的话,可以把应用自带的域名,替换成自己的,然后按接口需要的返回值,给他返回响应的数据格式即可。这个实例仅需要修改两处即可。

    # 重打包发版思路

    把解压的文件夹打包回 asar格式的文件即可, 这个网上一大把资料。

    # 对于electron加密方式的思考

    相对于原生开发来说,js安全做客户端毕竟薄弱,UI交互是没问题的,关键代码可以放到dll、so层去做,但是也没办法避免从js层面去剥离dll层函数的调用。所以目前来说并没有很好的解决方案,本文只是起到抛砖引玉的作用。期待electron有更好、更安全的解决方案。
    `

  4. 又是 Electron!Element 桌面版被发现远程代码执行
    https://mp.weixin.qq.com/s/bcgtMXmx_yRvSR2olvOKhA
    `
    Remote Code Execution on Element Desktop Application using Node Integration in Sub Frames Bypass – CVE-2022-23597

    Element 是一款基于 Matrix 协议的即时通讯软件,支持多个桌面和移动平台,允许端到端加密、拉群、语音视频通话和自建服务器等功能。

    Element 的桌面端主要还是用 Electron。一个有趣的现象是,只要一款 App 而且足够流行,而且选择使用 Electron,那么一定会被人搞出 XSS 甚至 RCE 漏洞来。

    2018 年 5 月,Signal 桌面端很短的时间内连续发现两个 XSS
    2020 年 8 月,另一款以安全为卖点的跨平台即时通信软件 Wire 桌面端被发现没有对打开文件的参数做检查,可以远程运行可执行文件。
    2020 年 10 月,知名的即时聊天和社群工具 Discord 被发现 XSS 和远程代码执行。
    2021 年 7 月,还是 Discord。

    Electron 大大方便了桌面应用的开发,可是两大黑点广受诟病——大多数 Electron 应用都没几个功能,却要带上一整个 Chrome 引擎来浪费存储空间和性能;而用 js 做桌面应用极大降低了漏洞利用成本,经常栽在 XSS 之类问题上。

    哪怕是公认性能架构好性能高,同时还是 Electron 亲兄弟的 VSCode,也时不时出过安全问题。怎么说呢?虽然因噎废食不好,可是 Electron 的生态确实该领几张反思券。其他的应用,能用网页版尽量用网页版吧……
    `

  5. TAURI
    https://tauri.app/
    `
    Build an optimized, secure, and frontend-independent application for multi-platform deployment.

    Electron 的替代品,用来制作跨平台的桌面应用,使用 Rust 语言开发。它采用各平台自带的 WebView,缺点是支持的 Web API 会比较少,优点是打包产物体积小。
    `

  6. 文件桥
    https://github.com/ppz-pro/file-bridge
    `
    网页里的文件服务器
    一个简单的 JS 脚本,用来架设静态文件服务器。A 电脑在网页上打开一个本地文件目录,B 电脑就能下载里面的文件,两者不必在同一局域网。

    # 需要
    * 一个公网可访问的服务器
    * Node.js
    * https

    git clone https://github.com/ppz-pro/file-bridge.git
    cd file-bridge
    node file_bridge.js

    # 原理
    两个“客户端”之间没法直接“传递数据”,因为没有公网地址,于是就需要一个“桥”,连接两个“客户端”。提供文件供人下载的,我在这里叫它“提供端”,另一个叫“下载端”。

    1. “桥”为每一个“提供端”生成一个 id(以下称为“提供端 id”)
    2. “提供端”使用 File System API 读取用户指定的目录,把目录结构发给“桥”
    3. “下载端”根据“提供端 id”从“桥”那里获取目录结构
    4. “下载端”要下载文件时,向“桥”发送“下载请求”并指定“提供端 id”及文件路径,桥会把这个请求存起来
    5. 用户在“提供端”指定“允许下载的目录”后,“提供端”程序就开始每隔 1 秒向“桥”发请求:问一问“有没有谁想下载我的文件”
    6. 上两个步骤,一个想下载别人的文件,一个想让人下载,一拍即合,而传文件只需一行代码 http.IncomingMessage.pipe(http.ServerResponse)

    其实第 5 步的“每隔 1 秒”很膈应,但原生 Node.js 对 Websocket 支持度比较低,而专门封装一个 Websocket 可能需要几十甚至上百行代码,于是作罢。反正,,,,这只是个有趣的项目,我是说,,,一开始就没以实用为目的。当然,适当地改造一下,也可以很实用,但谁能拒绝“仅使用原生模块”的诱惑呢。

    这个项目更加深我那个刻板印象:编程的难点不在于“让人使用”,而是“不让人使用”,比如“非法用户”和“未付费用户”。其实“未付费用户”就是“非法用户
    `

回复 hi 取消回复

您的电子邮箱地址不会被公开。 必填项已用*标注