在调试中使用 Symbol Server

最后更新于:2022-04-01 20:50:52

# Setting Up Symbol Server in Debugger 调试 symbols 让你有更好的调试 sessions. 它们有可执行的动态库的函数信息,并且提供信息来获得洁净的呼叫栈. 一个 Symbol 服务器允许调试器自动加载正确的 symbols, 二进制文件 和 资源文件,不用再去强制用户下载巨大的调试文件. 服务器函数类似 [Microsoft's symbol server](http://support.microsoft.com/kb/311503) ,所以这里的记录可用. 注意,因为公众版本的 Electron 构建是最优化的,调试不一定一直简单.调试器将不会给显示出所有变量内容,并且因为内联,尾调用,和其它编译器优化,执行路径会看起来很怪异 . 唯一的解决办法是搭建一个不优化的本地构建. Electron 使用的官方 symbol 服务器地址为 `http://54.249.141.255:8086/atom-shell/symbols` . 你不能直接访问这个路径,必须将其添加到你的调试工具的 symbol 路径上.在下面的例子中,使用了一个本地缓存目录来避免重复从服务器获取 PDB. 在你的电脑上使用一个恰当的缓存目录来代替 `c:\code\symbols` . ## Using the Symbol Server in Windbg Windbg symbol 路径被配制为一个限制带星号字符的字符串. 要只使用 Electron 的 symbol 服务器, 将下列记录添加到你的 symbol 路径 (__注意:__ 如果你愿意使用一个不同的地点来下载 symbols,你可以在你的电脑中使用任何可写的目录来代替 `c:\code\symbols`): ``` SRV*c:\code\symbols\*http://54.249.141.255:8086/atom-shell/symbols ``` 使用 Windbg 菜单或通过输入 `.sympath` 命令,在环境中设置一个 `_NT_SYMBOL_PATH` 字符串.如果你也想从微软的 symbol 服务器获得 symbols ,你应当首先将它们先列出来 : ``` SRV*c:\code\symbols\*http://msdl.microsoft.com/download/symbols;SRV*c:\code\symbols\*http://54.249.141.255:8086/atom-shell/symbols ``` ## 在 Visual Studio 中使用 symbol 服务器 ## Troubleshooting: Symbols will not load 在 Windbg 中输入下列命令,打印出未什么 symbols 没有加载 : ``` > !sym noisy > .reload /f chromiumcontent.dll ```
';

构建步骤(Linux)

最后更新于:2022-04-01 20:50:49

# Build Instructions (Linux) 遵循下面的引导,在 Linux 上构建 Electron . ## Prerequisites * Python 2.7.x. 一些发行版如 CentOS 仍然使用 Python 2.6.x ,所以或许需要 check 你的 Python 版本,使用 `python -V`. * Node.js v0.12.x. 有很多方法来安装 Node. 可以从 [Node.js](http://nodejs.org)下载原文件并且编译它 .也可以作为一个标准的用户在 home 目录下安装 node .或者尝试使用仓库 [NodeSource](https://nodesource.com/blog/nodejs-v012-iojs-and-the-nodesource-linux-repositories). * Clang 3.4 或更新的版本. * GTK+开发头文件和libnotify. 在 Ubuntu, 安装下面的库 : ```bash $ sudo apt-get install build-essential clang libdbus-1-dev libgtk2.0-dev \ libnotify-dev libgnome-keyring-dev libgconf2-dev \ libasound2-dev libcap-dev libcups2-dev libxtst-dev \ libxss1 libnss3-dev gcc-multilib g++-multilib ``` 在 Fedora, 安装下面的库 : ```bash $ sudo yum install clang dbus-devel gtk2-devel libnotify-devel libgnome-keyring-devel \ xorg-x11-server-utils libcap-devel cups-devel libXtst-devel \ alsa-lib-devel libXrandr-devel GConf2-devel nss-devel ``` 其它版本的也许提供了相似的包来安装,通过包管理器,例如 pacman. 或一个可以编译源文件的. ## 使用虚拟机 如果在虚拟机上构建 Electron,你需要一个固定大小的设备,至少需要 25 gigabytes . ## 获取代码 ```bash $ git clone https://github.com/electron/electron.git ``` ## Bootstrapping bootstrap 脚本也是必要下载的构建依赖,来创建项目文件.需要使用 Python 2.7.x 来让脚本成功执行.正确下载文件会花费较长的时间. 注意我们使用的是 `ninja` 来构建 Electron,所以没有生成 `Makefile` 项目. ```bash $ cd electron $ ./script/bootstrap.py -v ``` ### 交叉编译 如果想创建一个 `arm` target ,应当还要下载下面的依赖 : ```bash $ sudo apt-get install libc6-dev-armhf-cross linux-libc-dev-armhf-cross \ g++-arm-linux-gnueabihf ``` 为了编译 `arm` 或 `ia32` targets, 你应当为 `bootstrap.py` 脚本使用 `--target_arch` 参数: ```bash $ ./script/bootstrap.py -v --target_arch=arm ``` ## 构建 创建 `Release` 、 `Debug` target: ```bash $ ./script/build.py ``` 这个脚本也许会在目录 `out/R` 下创建一个巨大的可执行的 Electron . 文件大小或许会超过 1.3 gigabytes. 原因是 Release target 二进制文件包含了 调试符号 .运行 `create-dist.py` 脚本来减小文件的 size : ```bash $ ./script/create-dist.py ``` 这会在 `dist` 目录下创建一个有大量小文件的工作空间. 运行 create-dist.py 脚本之后, 或许你想删除仍然在 `out/R` 下的 1.3+ gigabyte 二进制文件. 可以只创建 `Debug` target: ```bash $ ./script/build.py -c D ``` 创建完毕, 可以在 `out/D`下面找到 `electron`. ## Cleaning 删除构建文件 : ```bash $ ./script/clean.py ``` ## 解决问题 确保你已经安装了所有的依赖 . ### Error While Loading Shared Libraries: libtinfo.so.5 预构建的 `clang` 会尝试链接到 `libtinfo.so.5`. 取决于 host 架构, 适当的使用 `libncurses`: ```bash $ sudo ln -s /usr/lib/libncurses.so.5 /usr/lib/libtinfo.so.5 ``` ## Tests 测试你的修改是否符合项目代码风格,使用: ```bash $ ./script/cpplint.py ``` 测试有效性使用: ```bash $ ./script/test.py ```
';

构建步骤(Windows)

最后更新于:2022-04-01 20:50:47

# Build Instructions (Windows) 遵循下面的引导,在 Windows 上构建 Electron . ## 前提 * Windows 7 / Server 2008 R2 or higher * Visual Studio 2013 with Update 4 - [download VS 2013 Community Edition for free](https://www.visualstudio.com/news/vs2013-community-vs). * [Python 2.7](http://www.python.org/download/releases/2.7/) * [Node.js](http://nodejs.org/download/) * [Git](http://git-scm.com) 如果你现在还没有安装 Windows , [modern.ie](https://www.modern.ie/en-us/virtualization-tools#downloads) 有一个 timebombed 版本的 Windows ,你可以用它来构建 Electron. 构建 Electron 完全的依赖于命令行,并且不可通过 Visual Studio. 可以使用任何的编辑器来开发 Electron ,未来会支持 Visual Studio. **注意:** 虽然 Visual Studio 不是用来构建的,但是它仍然 **必须的** ,因为我们需要它提供的构建工具栏. **注意:** Visual Studio 2015 不可用. 请确定使用 MSVS **2013**. ## 获取代码 ```powershell $ git clone https://github.com/electron/electron.git ``` ## Bootstrapping bootstrap 脚本也是必要下载的构建依赖,来创建项目文件.注意我们使用的是 `ninja` 来构建 Electron,所以没有生成 Visual Studio 项目. ```powershell $ cd electron $ python script\bootstrap.py -v ``` ## 构建 创建 `Release` 、 `Debug` target: ```powershell $ python script\build.py ``` 可以只创建 `Debug` target: ```powershell $ python script\build.py -c D ``` 创建完毕, 可以在 `out/D`(debug target) 或 `out\R` (release target) 下面找到 `electron.exe`. ## 64bit Build 为了构建64位的 target,在运行 bootstrap 脚本的时候需要使用 `--target_arch=x64` : ```powershell $ python script\bootstrap.py -v --target_arch=x64 ``` 其他构建步骤完全相同. ## Tests 测试你的修改是否符合项目代码风格,使用: ```powershell $ python script\cpplint.py ``` 测试有效性使用: ```powershell $ python script\test.py ``` 在构建 debug 时为 Tests包含原生模块 (例如 `runas`) 将不会执行(详情 [#2558](https://github.com/electron/electron/issues/2558)), 但是它们在构建 release 会起效. 运行 release 构建使用 : ```powershell $ python script\test.py -R ``` ## 解决问题 ### Command xxxx not found 如果你遇到了一个错误,类似 `Command xxxx not found`, 可以尝试使用 `VS2012 Command Prompt` 控制台来执行构建脚本 . ### Fatal internal compiler error: C1001 确保你已经安装了 Visual Studio 的最新安装包 . ### Assertion failed: ((handle))->activecnt >= 0 如果在 Cygwin 下构建的,你可能会看到 `bootstrap.py` 失败并且附带下面错误 : ``` Assertion failed: ((handle))->activecnt >= 0, file src\win\pipe.c, line 1430 Traceback (most recent call last): File "script/bootstrap.py", line 87, in sys.exit(main()) File "script/bootstrap.py", line 22, in main update_node_modules('.') File "script/bootstrap.py", line 56, in update_node_modules execute([NPM, 'install']) File "/home/zcbenz/codes/raven/script/lib/util.py", line 118, in execute raise e subprocess.CalledProcessError: Command '['npm.cmd', 'install']' returned non-zero exit status 3 ``` 这是由同时使用 Cygwin Python 和 Win32 Node 造成的 bug.解决办法就是使用 Win32 Python 执行 bootstrap 脚本 (假定你已经在目录 `C:\Python27` 下安装了 Python): ```powershell $ /cygdrive/c/Python27/python.exe script/bootstrap.py ``` ### LNK1181: cannot open input file 'kernel32.lib' 重新安装 32位的 Node.js. ### Error: ENOENT, stat 'C:\Users\USERNAME\AppData\Roaming\npm' 简单创建目录 [应该可以解决问题](http://stackoverflow.com/a/25095327/102704): ```powershell $ mkdir ~\AppData\Roaming\npm ``` ### node-gyp is not recognized as an internal or external command 如果你使用 Git Bash 来构建,或许会遇到这个错误,可以使用 PowerShell 或 VS2012 Command Prompt 来代替 .
';

构建步骤(OS X)

最后更新于:2022-04-01 20:50:45

# Build Instructions (OS X) 遵循下面的引导,在 OS X 上构建 Electron . ## 前提 * OS X >= 10.8 * [Xcode](https://developer.apple.com/technologies/tools/) >= 5.1 * [node.js](http://nodejs.org) (外部) 如果你通过 Homebrew 使用 Python 下载,需要安装下面的 Python 模块: * pyobjc ## 获取代码 ```bash $ git clone https://github.com/electron/electron.git ``` ## Bootstrapping bootstrap 脚本也是必要下载的构建依赖,来创建项目文件.注意我们使用的是 [ninja](https://ninja-build.org/) 来构建 Electron,所以没有生成 Xcode 项目. ```bash $ cd electron $ ./script/bootstrap.py -v ``` ## 构建 创建 `Release` 、 `Debug` target: ```bash $ ./script/build.py ``` 可以只创建 `Debug` target: ```bash $ ./script/build.py -c D ``` 创建完毕, 可以在 `out/D` 下面找到 `Electron.app`. ## 32位支持 在 OS X 上,构建 Electron 只支持 64位的,不支持 32位的 . ## 测试 测试你的修改是否符合项目代码风格,使用: ```bash $ ./script/cpplint.py ``` 测试有效性使用: ```bash $ ./script/test.py ```
';

构建系统概览

最后更新于:2022-04-01 20:50:42

# Build System Overview Electron 使用 [gyp](https://gyp.gsrc.io/) 来生成项目 ,使用 [ninja](https://ninja-build.org/) 来构建项目. 项目配置可以在 `.gyp` 和 `.gypi` 文件中找到. ## Gyp 文件 下面的 `gyp` 文件包含了构建 Electron 的主要规则 : * `atom.gyp` 定义了 Electron 它自己是怎样被构建的. * `common.gypi` 调整 node 的构建配置,来让它结合 Chromium 一起构建. * `vendor/brightray/brightray.gyp` 定义了 `brightray` 是如何被构建的,并且包含了默认配置来连接到 Chromium. * `vendor/brightray/brightray.gypi` 包含了常用的创建配置. ## 创建组件 在 Chromium 还是一个相当大的项目的时候,最后链接阶段会花了好几分钟,这让开发变得很困难. 为了解决这个困难,Chromium 引入了 "component build" ,这让每个创建的组建都是分隔开的共享库,让链接更快,但是这浪费了文件大小和性能. 在 Electron 中,我们采用了一个非常相似的方法 : 在创建 `Debug` , 二进制文件会被链接进入一个 Chromium 组件的共享版本库来达到快速链接; 在创建 `Release`, 二进制文件会被链接进入一个静态版本库, 所以我们可以有最小的二进制文件size和最佳的体验. ## Minimal Bootstrapping 在运行 bootstrap 脚本的时候,所有的 Chromium 预编译二进制文件会被下载.默认静态库和共享库会被下载,并且项目的最后大小会在 800MB 到 2GB 之间,这取决于平台类型. 默认,`libchromiumcontent` 是从 Amazon Web Services 上下载下来的.如果设置了 `LIBCHROMIUMCONTENT_MIRROR` 环境变量,bootstrap脚本会从这里下载下来. [`libchromiumcontent-qiniu-mirror`](https://github.com/hokein/libchromiumcontent-qiniu-mirror) 是 `libchromiumcontent` 的映射.如果你不能连接 AWS,你可以切换下载路径:`export LIBCHROMIUMCONTENT_MIRROR=http://7xk3d2.dl1.z0.glb.clouddn.com/` 如果只是想快速搭建一个 Electron 的测试或开发环境,可以通过 `--dev` 参数只下载共享版本库: ```bash $ ./script/bootstrap.py --dev $ ./script/build.py -c D ``` ## Two-Phase Project Generation 在 `Release` 和 `Debug` 构建的时候后,Electron 链接了不同配置的库 .然而 `gyp`不支持为不同的配置文件进行不同的链接设置. 为了规避这个问题,Electron 在运行 `gyp` 的时候,使用了一个 `gyp` 的变量 `libchromiumcontent_component`来控制应该使用哪个链接设置,并且只生成一个目标. ## Target Names 与大多数的项目不同,它们使用 `Release` 和 `Debug` 作为目标名字,而 Electron 使用使用的是 `R` 和 `D`.这是因为如果只定义了一个 `Release` 或 `Debug` 构建配置,`gyp` 会随机崩溃,并且在同一时候,Electron 只生成一个目标,如上所述. 这只对开发者可用,如果想重新构建 Electron ,将不会成功.
';

与 NW.js(原 node-webkit)在技术上的差异

最后更新于:2022-04-01 20:50:40

# Electron 和 NW.js (原名 node-webkit) 在技术上的差异 __备注:Electron 的原名是 Atom Shell。__ 与 NW.js 相似,Electron 提供了一个能通过 JavaScript 和 HTML 创建桌面应用的平台,同时集成 Node 来授予网页访问底层系统的权限。 但是这两个项目也有本质上的区别,使得 Electron 和 NW.js 成为两个相互独立的产品。 __1. 应用的入口__ 在 NW.js 中,一个应用的主入口是一个页面。你在 `package.json` 中指定一个主页面,它会作为应用的主窗口被打开。 在 Electron 中,入口是一个 JavaScript 脚本。不同于直接提供一个URL,你需要手动创建一个浏览器窗口,然后通过 API 加载 HTML 文件。你还可以监听窗口事件,决定何时让应用退出。 Electron 的工作方式更像 Node.js 运行时。 Electron 的 APIs 更加底层,因此你可以用它替代 [PhantomJS](http://phantomjs.org/) 做浏览器测试。 __2. 构建系统__ 为了避免构建整个 Chromium 带来的复杂度,Electron 通过 [`libchromiumcontent`](https://github.com/brightray/libchromiumcontent) 来访问 Chromium 的 Content API。`libchromiumcontent` 是一个独立的、引入了 Chromium Content 模块及其所有依赖的共享库。用户不需要一个强劲的机器来构建 Electron。 __3. Node 集成__ 在 NW.js,网页中的 Node 集成需要通过给 Chromium 打补丁来实现。但在 Electron 中,我们选择了另一种方式:通过各个平台的消息循环与 libuv 的循环集成,避免了直接在 Chromium 上做改动。你可以看 [`node_bindings`][node-bindings] 来了解这是如何完成的。 __4. 多上下文__ 如果你是有经验的 NW.js 用户,你应该会熟悉 Node 上下文和 web 上下文的概念。这些概念的产生源于 NW.js 的实现方式。 通过使用 Node 的[多上下文](http://strongloop.com/strongblog/whats-new-node-js-v0-12-multiple-context-execution/)特性,Electron不需要在网页中引入新的 JavaScript 上下文。 [node-bindings]: https://github.com/electron/electron/tree/master/atom/common
';

源码目录结构

最后更新于:2022-04-01 20:50:38

# 源码目录结构 Electron 的源代码主要依据 Chromium 的拆分约定被拆成了许多部分。 为了更好地理解源代码,您可能需要了解一下 [Chromium 的多进程架构](http://dev.chromium.org/developers/design-documents/multi-process-architecture)。 ## 源代码的结构 ``` Electron ├──atom - Electron 的源代码 | ├── app - 系统入口代码 | ├── browser - 包含了主窗口、UI 和其他所有与主进程有关的东西,它会告诉渲染进程如何管理页面 | |   ├── lib - 主进程初始化代码中 JavaScript 部分的代码 | | ├── ui - 不同平台上 UI 部分的实现 | | | ├── cocoa - Cocoa 部分的源代码 | | | ├── gtk - GTK+ 部分的源代码 | | | └── win - Windows GUI 部分的源代码 | | ├── default_app - 在没有指定 app 的情况下 Electron 启动时默认显示的页面 | | ├── api - 主进程 API 的实现 | | | └── lib - API 实现中 Javascript 部分的代码 | | ├── net - 网络相关的代码 | | ├── mac - 与 Mac 有关的 Objective-C 代码 | | └── resources - 图标,平台相关的文件等 | ├── renderer - 运行在渲染进程中的代码 | | ├── lib - 渲染进程初始化代码中 JavaScript 部分的代码 | | └── api - 渲染进程 API 的实现 | | └── lib - API 实现中 Javascript 部分的代码 | └── common - 同时被主进程和渲染进程用到的代码,包括了一些用来将 node 的事件循环 | | 整合到 Chromium 的事件循环中时用到的工具函数和代码 | ├── lib - 同时被主进程和渲染进程使用到的 Javascript 初始化代码 | └── api - 同时被主进程和渲染进程使用到的 API 的实现以及 Electron 内置模块的基础设施 | └── lib - API 实现中 Javascript 部分的代码 ├── chromium_src - 从 Chromium 项目中拷贝来的代码 ├── docs - 英语版本的文档 ├── docs-translations - 各种语言版本的文档翻译 ├── spec - 自动化测试 ├── atom.gyp - Electron 的构建规则 └── common.gypi - 为诸如 `node` 和 `breakpad` 等其他组件准备的编译设置和构建规则 ``` ## 其他目录的结构 * **script** - 用于诸如构建、打包、测试等开发用途的脚本 * **tools** - 在 gyp 文件中用到的工具脚本,但与 `script` 目录不同, 该目录中的脚本不应该被用户直接调用 * **vendor** - 第三方依赖项的源代码,为了防止人们将它与 Chromium 源码中的同名目录相混淆, 在这里我们不使用 `third_party` 作为目录名 * **node_modules** - 在构建中用到的第三方 node 模块 * **out** - `ninja` 的临时输出目录 * **dist** - 由脚本 `script/create-dist.py` 创建的临时发布目录 * **external_binaries** - 下载的不支持通过 `gyp` 构建的预编译第三方框架
';

代码规范

最后更新于:2022-04-01 20:50:36

# 编码规范 以下是 Electron 项目的编码规范。 ## C++ 和 Python 对于 C++ 和 Python,我们遵循 Chromium 的[编码规范](http://www.chromium.org/developers/coding-style)。你可以使用 `script/cpplint.py` 来检验文件是否符合要求。 我们目前使用的 Pyhton 版本是 Python 2.7。 C++ 代码中用到了许多 Chromium 中的接口和数据类型,所以希望你能熟悉它们。Chromium 中的[重要接口和数据结构](https://www.chromium.org/developers/coding-style/important-abstractions-and-data-structures)就是一篇不错的入门文档,里面提到了一些特殊类型、域内类型(退出作用域时自动释放内存)、日志机制,等等。 ## CoffeeScript 对于 CoffeeScript,我们遵循 GitHub 的[编码规范](https://github.com/styleguide/javascript) 及以下规则: * 文件**不要**以换行符结尾,我们要遵循 Google 的编码规范。 * 文件名使用 `-` 而不是 `_` 来连接单词,比如 `file-name.coffee` 而不是 `file_name.coffee`,这是沿用 [github/atom](https://github.com/github/atom) 模块的命名方式(`module-name`)。这条规则仅适用于 `.coffee` 文件。 ## API 命名 当新建一个 API 时,我们倾向于使用 getters 和 setters 而不是 jQuery 单函数的命名方式,比如 `.getText()` 和 `.setText(text)` 而不是 `.text([text])`。这里有关于该规则的[讨论记录](https://github.com/electron/electron/issues/46)。
';

开发

最后更新于:2022-04-01 20:50:33

# 开发
';

shell

最后更新于:2022-04-01 20:50:31

# shell `shell` 模块提供了集成其他桌面客户端的关联功能. 在用户默认浏览器中打开URL的示例: ```javascript var shell = require('shell'); shell.openExternal('https://github.com'); ``` ## Methods `shell` 模块包含以下函数: ### `shell.showItemInFolder(fullPath)` * `fullPath` String 打开文件所在文件夹,一般情况下还会选中它. ### `shell.openItem(fullPath)` * `fullPath` String 以默认打开方式打开文件. ### `shell.openExternal(url)` * `url` String 以系统默认设置打开外部协议.(例如,mailto: somebody@somewhere.io会打开用户默认的邮件客户端) ### `shell.moveItemToTrash(fullPath)` * `fullPath` String 删除指定路径文件,并返回此操作的状态值(boolean类型). ### `shell.beep()` 播放 beep 声音.
';

screen

最后更新于:2022-04-01 20:50:29

# screen `screen` 模块检索屏幕的 size,显示,鼠标位置等的信息.在 `app` 模块的`ready` 事件触发之前不可使用这个模块. `screen` 是一个 [EventEmitter](http://nodejs.org/api/events.html#events_class_events_eventemitter). **注意:** 在渲染进程 / 开发者工具栏, `window.screen` 是一个预设值的 DOM 属性, 所以这样写 `var screen = require('electron').screen` 将不会工作. 在我们下面的例子, 我们取代使用可变名字的 `electronScreen`. 一个例子,创建一个充满真个屏幕的窗口 : ```javascript const electron = require('electron'); const app = electron.app; const BrowserWindow = electron.BrowserWindow; var mainWindow; app.on('ready', function() { var electronScreen = electron.screen; var size = electronScreen.getPrimaryDisplay().workAreaSize; mainWindow = new BrowserWindow({ width: size.width, height: size.height }); }); ``` 另一个例子,在次页外创建一个窗口: ```javascript const electron = require('electron'); const app = electron.app; const BrowserWindow = electron.BrowserWindow; var mainWindow; app.on('ready', function() { var electronScreen = electron.screen; var displays = electronScreen.getAllDisplays(); var externalDisplay = null; for (var i in displays) { if (displays[i].bounds.x != 0 || displays[i].bounds.y != 0) { externalDisplay = displays[i]; break; } } if (externalDisplay) { mainWindow = new BrowserWindow({ x: externalDisplay.bounds.x + 50, y: externalDisplay.bounds.y + 50 }); } }); ``` ## `Display` 对象 `Display` 对象表示了物力方式连接系统. 一个伪造的 `Display` 或许存在于一个无头系统中,或者一个 `Display` 相当于一个远程的、虚拟的 display. * `display` object * `id` Integer - 与display 相关的唯一性标志. * `rotation` Integer - 可以是 0, 1, 2, 3, 每个代表了屏幕旋转的度数 0, 90, 180, 270. * `scaleFactor` Number - Output device's pixel scale factor. * `touchSupport` String - 可以是 `available`, `unavailable`, `unknown`. * `bounds` Object * `size` Object * `workArea` Object * `workAreaSize` Object ## 事件 `screen` 模块有如下事件: ### Event: 'display-added' 返回: * `event` Event * `newDisplay` Object 当添加了 `newDisplay` 时发出事件 ### Event: 'display-removed' 返回: * `event` Event * `oldDisplay` Object 当移出了 `oldDisplay` 时发出事件 ### Event: 'display-metrics-changed' 返回: * `event` Event * `display` Object * `changedMetrics` Array 当一个 `display` 中的一个或更多的 metrics 改变时发出事件. `changedMetrics` 是一个用来描述这个改变的数组.可能的变化为 `bounds`, `workArea`, `scaleFactor` 和 `rotation`. ## 方法 `screen` 模块有如下方法: ### `screen.getCursorScreenPoint()` 返回当前鼠标的绝对路径 . ### `screen.getPrimaryDisplay()` 返回最主要的 display. ### `screen.getAllDisplays()` 返回一个当前可用的 display 数组. ### `screen.getDisplayNearestPoint(point)` * `point` Object * `x` Integer * `y` Integer 返回离指定点最近的 display. ### `screen.getDisplayMatching(rect)` * `rect` Object * `x` Integer * `y` Integer * `width` Integer * `height` Integer 返回与提供的边界范围最密切相关的 display.
';

nativeImage

最后更新于:2022-04-01 20:50:27

# nativeImage 在 Electron 中, 对所有创建 images 的 api 来说, 你可以使用文件路径或 `nativeImage` 实例. 如果使用 `null` ,将创建一个空的image 对象. 例如, 当创建一个 tray 或设置窗口的图标时候,你可以使用一个字符串的图片路径 : ```javascript var appIcon = new Tray('/Users/somebody/images/icon.png'); var window = new BrowserWindow({icon: '/Users/somebody/images/window.png'}); ``` 或者从剪切板中读取图片,它返回的是 `nativeImage`: ```javascript var image = clipboard.readImage(); var appIcon = new Tray(image); ``` ## 支持的格式 当前支持 `PNG` 和 `JPEG` 图片格式. 推荐 `PNG` ,因为它支持透明和无损压缩. 在 Windows, 你也可以使用 `ICO` 图标的格式. ## 高分辨率图片 如果平台支持 high-DPI,你可以在图片基础路径后面添加 `@2x` ,可以标识它为高分辨率的图片. 例如,如果 `icon.png` 是一个普通图片并且拥有标准分辨率,然后 `icon@2x.png`将被当作高分辨率的图片处理,它将拥有双倍 DPI 密度. 如果想同时支持展示不同分辨率的图片,你可以将拥有不同size 的图片放在同一个文件夹下,不用 DPI 后缀.例如 : ```text images/ ├── icon.png ├── icon@2x.png └── icon@3x.png ``` ```javascript var appIcon = new Tray('/Users/somebody/images/icon.png'); ``` 也支持下面这些 DPI 后缀: * `@1x` * `@1.25x` * `@1.33x` * `@1.4x` * `@1.5x` * `@1.8x` * `@2x` * `@2.5x` * `@3x` * `@4x` * `@5x` ## 模板图片 模板图片由黑色和清色(和一个 alpha 通道)组成. 模板图片不是单独使用的,而是通常和其它内容混合起来创建期望的最终效果. 最常见的用力是将模板图片用到菜单栏图片上,所以它可以同时适应亮、黑不同的菜单栏. **注意:** 模板图片只在 OS X 上可用. 为了将图片标识为一个模板图片,它的文件名应当以 `Template` 结尾. 例如: * `xxxTemplate.png` * `xxxTemplate@2x.png` ## 方法 `nativeImage` 类有如下方法: ### `nativeImage.createEmpty()` 创建一个空的 `nativeImage` 实例. ### `nativeImage.createFromPath(path)` * `path` String 从指定 `path` 创建一个新的 `nativeImage` 实例 . ### `nativeImage.createFromBuffer(buffer[, scaleFactor])` * `buffer` [Buffer][buffer] * `scaleFactor` Double (可选) 从 `buffer` 创建一个新的 `nativeImage` 实例 .默认 `scaleFactor` 是 1.0. ### `nativeImage.createFromDataURL(dataURL)` * `dataURL` String 从 `dataURL` 创建一个新的 `nativeImage` 实例 . ## 实例方法 `nativeImage` 有如下方法: ```javascript const nativeImage = require('electron').nativeImage; var image = nativeImage.createFromPath('/Users/somebody/images/icon.png'); ``` ### `image.toPng()` 返回一个 [Buffer][buffer] ,它包含了图片的 `PNG` 编码数据. ### `image.toJpeg(quality)` * `quality` Integer (**必须**) - 在 0 - 100 之间. 返回一个 [Buffer][buffer] ,它包含了图片的 `JPEG` 编码数据. ### `image.toDataURL()` 返回图片数据的 URL. ### `image.getNativeHandle()` _OS X_ 返回一个保存了 c 指针的 [Buffer][buffer] 来潜在处理原始图像.在OS X, 将会返回一个 `NSImage` 指针实例. 注意那返回的指针是潜在原始图像的弱指针,而不是一个复制,你_必须_ 确保与 `nativeImage` 的关联不间断 . ### `image.isEmpty()` 返回一个 boolean ,标识图片是否为空. ### `image.getSize()` 返回图片的 size. [buffer]: https://nodejs.org/api/buffer.html#buffer_class_buffer ### `image.setTemplateImage(option)` * `option` Boolean 将图片标识为模板图片. ### `image.isTemplateImage()` 返回一个 boolean ,标识图片是否是模板图片.
';

crashReporter

最后更新于:2022-04-01 20:50:24

# crashReporter `crash-reporter` 模块开启发送应用崩溃报告. 下面是一个自动提交崩溃报告给服务器的例子 : ```javascript const crashReporter = require('electron').crashReporter; crashReporter.start({ productName: 'YourName', companyName: 'YourCompany', submitURL: 'https://your-domain.com/url-to-submit', autoSubmit: true }); ``` 可以使用下面的项目来创建一个服务器,用来接收和处理崩溃报告 : * [socorro](https://github.com/mozilla/socorro) * [mini-breakpad-server](https://github.com/atom/mini-breakpad-server) ## 方法 `crash-reporter` 模块有如下方法: ### `crashReporter.start(options)` * `options` Object * `companyName` String * `submitURL` String - 崩溃报告发送的路径,以post方式. * `productName` String (可选) - 默认为 `Electron`. * `autoSubmit` Boolean - 是否自动提交. 默认为 `true`. * `ignoreSystemCrashHandler` Boolean - 默认为 `false`. * `extra` Object - 一个你可以定义的对象,附带在崩溃报告上一起发送 . 只有字符串属性可以被正确发送,不支持嵌套对象. 只可以在使用其它 `crashReporter` APIs 之前使用这个方法. **注意:** 在 OS X, Electron 使用一个新的 `crashpad` 客户端, 与 Windows 和 Linux 的 `breakpad` 不同. 为了开启崩溃点搜集,你需要在主进程和其它每个你需要搜集崩溃报告的渲染进程中调用 `crashReporter.start` API 来初始化 `crashpad`. ### `crashReporter.getLastCrashReport()` 返回最后一个崩溃报告的日期和 ID.如果没有过崩溃报告发送过来,或者还没有开始崩溃报告搜集,将返回 `null` . ### `crashReporter.getUploadedReports()` 返回所有上载的崩溃报告,每个报告包含了上载日期和 ID. ## crash-reporter Payload 崩溃报告将发送下面 `multipart/form-data` `POST` 型的数据给 `submitURL` : * `ver` String - Electron 版本. * `platform` String - 例如 'win32'. * `process_type` String - 例如 'renderer'. * `guid` String - 例如 '5e1286fc-da97-479e-918b-6bfb0c3d1c72' * `_version` String - `package.json` 版本. * `_productName` String - `crashReporter` `options` 对象中的产品名字. * `prod` String - 基础产品名字. 这种情况为 Electron. * `_companyName` String - `crashReporter` `options` 对象中的公司名字. * `upload_file_minidump` File - 崩溃报告按照 `minidump` 的格式. * `crashReporter` 中的 `extra` 对象的所有等级和一个属性. `options` object
';

clipboard

最后更新于:2022-04-01 20:50:22

# clipboard `clipboard` 模块提供方法来供复制和粘贴操作 . 下面例子展示了如何将一个字符串写道 clipboard 上: ```javascript const clipboard = require('electron').clipboard; clipboard.writeText('Example String'); ``` 在 X Window 系统上, 有一个可选的 clipboard. 你可以为每个方法使用 `selection` 来控制它: ```javascript clipboard.writeText('Example String', 'selection'); console.log(clipboard.readText('selection')); ``` ## 方法 `clipboard` 模块有以下方法: **注意:** 测试 APIs 已经标明,并且在将来会被删除 . ### `clipboard.readText([type])` * `type` String (可选) 以纯文本形式从 clipboard 返回内容 . ### `clipboard.writeText(text[, type])` * `text` String * `type` String (可选) 以纯文本形式向 clipboard 添加内容 . ### `clipboard.readHtml([type])` * `type` String (可选) 返回 clipboard 中的标记内容. ### `clipboard.writeHtml(markup[, type])` * `markup` String * `type` String (可选) 向 clipboard 添加 `markup` 内容 . ### `clipboard.readImage([type])` * `type` String (可选) 从 clipboard 中返回 [NativeImage](native-image.md) 内容. ### `clipboard.writeImage(image[, type])` * `image` [NativeImage](native-image.md) * `type` String (可选) 向 clipboard 中写入 `image` . ### `clipboard.readRtf([type])` * `type` String (可选) 从 clipboard 中返回 RTF 内容. ### `clipboard.writeRtf(text[, type])` * `text` String * `type` String (可选) 向 clipboard 中写入 RTF 格式的 `text` . ### `clipboard.clear([type])` * `type` String (可选) 清空 clipboard 内容. ### `clipboard.availableFormats([type])` * `type` String (可选) 返回 clipboard 支持的格式数组 . ### `clipboard.has(data[, type])` _Experimental_ * `data` String * `type` String (可选) 返回 clipboard 是否支持指定 `data` 的格式. ```javascript console.log(clipboard.has('

selection

')); ``` ### `clipboard.read(data[, type])` _Experimental_ * `data` String * `type` String (可选) 读取 clipboard 的 `data`. ### `clipboard.write(data[, type])` * `data` Object * `text` String * `html` String * `image` [NativeImage](native-image.md) * `type` String (可选) ```javascript clipboard.write({text: 'test', html: "test"}); ``` 向 clipboard 写入 `data` .
';

在两种进程中都可用的模块

最后更新于:2022-04-01 20:50:20

# 在两种进程中都可用的模块
';

webFrame

最后更新于:2022-04-01 20:50:18

# webFrame `web-frame` 模块允许你自定义如何渲染当前网页 . 例子,放大当前页到 200%. ```javascript var webFrame = require('electron').webFrame; webFrame.setZoomFactor(2); ``` ## 方法 `web-frame` 模块有如下方法: ### `webFrame.setZoomFactor(factor)` * `factor` Number - 缩放参数. 将缩放参数修改为指定的参数值.缩放参数是百分制的,所以 300% = 3.0. ### `webFrame.getZoomFactor()` 返回当前缩放参数值. ### `webFrame.setZoomLevel(level)` * `level` Number - 缩放水平 将缩放水平修改为指定的水平值. 原始 size 为 0 ,并且每次增长都表示放大 20% 或缩小 20%,默认限制为原始 size 的 300% 到 50% 之间 . ### `webFrame.getZoomLevel()` 返回当前缩放水平值. ### `webFrame.setZoomLevelLimits(minimumLevel, maximumLevel)` * `minimumLevel` Number * `maximumLevel` Number 设置缩放水平的最大值和最小值. ### `webFrame.setSpellCheckProvider(language, autoCorrectWord, provider)` * `language` String * `autoCorrectWord` Boolean * `provider` Object 为输入框或文本域设置一个拼写检查 provider . `provider` 必须是一个对象,它有一个 `spellCheck` 方法,这个方法返回扫过的单词是否拼写正确 . 例子,使用 [node-spellchecker][spellchecker] 作为一个 provider: ```javascript webFrame.setSpellCheckProvider("en-US", true, { spellCheck: function(text) { return !(require('spellchecker').isMisspelled(text)); } }); ``` ### `webFrame.registerURLSchemeAsSecure(scheme)` * `scheme` String 注册 `scheme` 为一个安全的 scheme. 安全的 schemes 不会引发混合内容 warnings.例如, `https` 和 `data` 是安全的 schemes ,因为它们不能被活跃网络攻击而失效. ### `webFrame.registerURLSchemeAsBypassingCSP(scheme)` * `scheme` String 忽略当前网页内容的安全策略,直接从 `scheme` 加载. ### `webFrame.registerURLSchemeAsPrivileged(scheme)` * `scheme` String 通过资源的内容安全策略,注册 `scheme` 为安全的 scheme,允许注册 ServiceWorker并且支持 fetch API. ### `webFrame.insertText(text)` * `text` String 向获得焦点的原色插入内容 . ### `webFrame.executeJavaScript(code[, userGesture])` * `code` String * `userGesture` Boolean (可选) - 默认为 `false`. 评估页面代码 . 在浏览器窗口中,一些 HTML APIs ,例如 `requestFullScreen`,只可以通过用户手势来使用.设置`userGesture` 为 `true` 可以突破这个限制 . [spellchecker]: https://github.com/atom/node-spellchecker
';

remote

最后更新于:2022-04-01 20:50:15

# remote `remote` 模块提供了一种在渲染进程(网页)和主进程之间进行进程间通讯(IPC)的简便途径。 Electron中, 与GUI相关的模块(如 `dialog`, `menu` 等)只存在于主进程,而不在渲染进程中 。为了能从渲染进程中使用它们,需要用`ipc`模块来给主进程发送进程间消息。使用 `remote` 模块,可以调用主进程对象的方法,而无需显式地发送进程间消息,这类似于 Java 的 [RMI][rmi]。 下面是从渲染进程创建一个浏览器窗口的例子: ```javascript const remote = require('electron').remote; const BrowserWindow = remote.BrowserWindow; var win = new BrowserWindow({ width: 800, height: 600 }); win.loadURL('https://github.com'); ``` **注意:** 反向操作(从主进程访问渲染进程),可以使用[webContents.executeJavascript](web-contents.md#webcontentsexecutejavascriptcode-usergesture). ## 远程对象 `remote`模块返回的每个对象(包括函数)都代表了主进程中的一个对象(我们称之为远程对象或者远程函数)。 当调用远程对象的方法、执行远程函数或者使用远程构造器(函数)创建新对象时,其实就是在发送同步的进程间消息。 在上面的例子中, `BrowserWindow` 和 `win` 都是远程对象,然而 `new BrowserWindow` 并没有在渲染进程中创建 `BrowserWindow` 对象。 而是在主进程中创建了 `BrowserWindow` 对象,并在渲染进程中返回了对应的远程对象,即 `win` 对象。 请注意只有 [可枚举属性](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties) 才能通过 remote 进行访问. ## 远程对象的生命周期 Electron 确保在渲染进程中的远程对象存在(换句话说,没有被垃圾收集),那主进程中的对应对象也不会被释放。 当远程对象被垃圾收集之后,主进程中的对应对象才会被取消关联。 如果远程对象在渲染进程泄露了(即,存在某个表中但永远不会释放),那么主进程中的对应对象也一样会泄露, 所以你必须小心不要泄露了远程对象。If the remote object is leaked in the renderer process (e.g. stored in a map but never freed), the corresponding object in the main process will also be leaked, so you should be very careful not to leak remote objects. 不过,主要的值类型如字符串和数字,是传递的副本。 ## 给主进程传递回调函数 在主进程中的代码可以从渲染进程——`remote`模块——中接受回调函数,但是使用这个功能的时候必须非常非常小心。Code in the main process can accept callbacks from the renderer - for instance the `remote` module - but you should be extremely careful when using this feature. 首先,为了避免死锁,传递给主进程的回调函数会进行异步调用。所以不能期望主进程来获得传递过去的回调函数的返回值。First, in order to avoid deadlocks, the callbacks passed to the main process are called asynchronously. You should not expect the main process to get the return value of the passed callbacks. 比如,你不能主进程中给`Array.map`传递来自渲染进程的函数。 ```javascript // 主进程 mapNumbers.js exports.withRendererCallback = function(mapper) { return [1,2,3].map(mapper); } exports.withLocalCallback = function() { return exports.mapNumbers(function(x) { return x + 1; }); } ``` ```javascript // 渲染进程 var mapNumbers = require("remote").require("./mapNumbers"); var withRendererCb = mapNumbers.withRendererCallback(function(x) { return x + 1; }) var withLocalCb = mapNumbers.withLocalCallback() console.log(withRendererCb, withLocalCb) // [true, true, true], [2, 3, 4] ``` 如你所见,渲染器回调函数的同步返回值没有按预期产生,与主进程中的一模一样的回调函数的返回值不同。 其次,传递给主进程的函数会持续到主进程对他们进行垃圾回收。 例如,下面的代码第一眼看上去毫无问题。给远程对象的`close`事件绑定了一个回调函数: ```javascript remote.getCurrentWindow().on('close', function() { // blabla... }); ``` 但记住主进程会一直保持对这个回调函数的引用,除非明确的卸载它。如果不卸载,每次重新载入窗口都会再次绑定,这样每次重启就会泄露一个回调函数。 更严重的是,由于前面安装了回调函数的上下文已经被释放,所以当主进程的 `close` 事件触发的时候,会抛出异常。 为了避免这个问题,要确保对传递给主进程的渲染器的回调函数进行清理。可以清理事件处理器,或者明确告诉主进行取消来自已经退出的渲染器进程中的回调函数。 ## 访问主进程中的内置模块 在主进程中的内置模块已经被添加为`remote`模块中的属性,所以可以直接像使用`electron`模块一样直接使用它们。 ```javascript const app = remote.app; ``` ## 方法 `remote` 模块有以下方法: ### `remote.require(module)` * `module` String 返回在主进程中执行 `require(module)` 所返回的对象。 ### `remote.getCurrentWindow()` 返回该网页所属的 [`BrowserWindow`](browser-window.md) 对象。 ### `remote.getCurrentWebContents()` 返回该网页的 [`WebContents`](web-contents.md) 对象 ### `remote.getGlobal(name)` * `name` String 返回在主进程中名为 `name` 的全局变量(即 `global[name]`) 。 ### `remote.process` 返回主进程中的 `process` 对象。等同于 `remote.getGlobal('process')` 但是有缓存。 [rmi]: http://en.wikipedia.org/wiki/Java_remote_method_invocation
';

ipcRenderer

最后更新于:2022-04-01 20:50:13

# ipcRenderer `ipcRenderer` 模块是一个 [EventEmitter](https://nodejs.org/api/events.html) 类的实例. 它提供了有限的方法,你可以从渲染进程向主进程发送同步或异步消息. 也可以收到主进程的相应. 查看 [ipcMain](ipc-main.md) 代码例子. ## 消息监听 `ipcRenderer` 模块有下列方法来监听事件: ### `ipcRenderer.on(channel, listener)` * `channel` String * `listener` Function 监听 `channel`, 当有新消息到达,使用 `listener(event, args...)` 调用 `listener` . ### `ipcRenderer.once(channel, listener)` * `channel` String * `listener` Function 为这个事件添加一个一次性 `listener` 函数.这个 `listener` 将在下一次有新消息被发送到 `channel` 的时候被请求调用,之后就被删除了. ### `ipcRenderer.removeListener(channel, listener)` * `channel` String * `listener` Function 从指定的 `channel` 中的监听者数组删除指定的 `listener` . ### `ipcRenderer.removeAllListeners([channel])` * `channel` String (optional) 删除所有的监听者,或者删除指定 `channel` 中的全部. ## 发送消息 `ipcRenderer` 模块有如下方法来发送消息: ### `ipcRenderer.send(channel[, arg1][, arg2][, ...])` * `channel` String * `arg` (可选) 通过 `channel` 向主进程发送异步消息,也可以发送任意参数.参数会被JSON序列化,之后就不会包含函数或原型链. 主进程通过使用 `ipcMain` 模块来监听 `channel`,从而处理消息. ### `ipcRenderer.sendSync(channel[, arg1][, arg2][, ...])` * `channel` String * `arg` (可选) 通过 `channel` 向主进程发送同步消息,也可以发送任意参数.参数会被JSON序列化,之后就不会包含函数或原型链. 主进程通过使用 `ipcMain` 模块来监听 `channel`,从而处理消息, 通过 `event.returnValue` 来响应. __注意:__ 发送同步消息将会阻塞整个渲染进程,除非你知道你在做什么,否则就永远不要用它 . ### `ipcRenderer.sendToHost(channel[, arg1][, arg2][, ...])` * `channel` String * `arg` (可选) 类似 `ipcRenderer.send` ,但是它的事件将发往 host page 的 `` 元素,而不是主进程.
';

desktopCapturer

最后更新于:2022-04-01 20:50:11

# desktopCapturer `desktopCapturer` 模块可用来获取可用资源,这个资源可通过 `getUserMedia` 捕获得到. ```javascript // 在渲染进程中. var desktopCapturer = require('electron').desktopCapturer; desktopCapturer.getSources({types: ['window', 'screen']}, function(error, sources) { if (error) throw error; for (var i = 0; i < sources.length; ++i) { if (sources[i].name == "Electron") { navigator.webkitGetUserMedia({ audio: false, video: { mandatory: { chromeMediaSource: 'desktop', chromeMediaSourceId: sources[i].id, minWidth: 1280, maxWidth: 1280, minHeight: 720, maxHeight: 720 } } }, gotStream, getUserMediaError); return; } } }); function gotStream(stream) { document.querySelector('video').src = URL.createObjectURL(stream); } function getUserMediaError(e) { console.log('getUserMediaError'); } ``` 当调用 `navigator.webkitGetUserMedia` 时创建一个约束对象,如果使用 `desktopCapturer` 的资源,必须设置 `chromeMediaSource` 为 `"desktop"` ,并且 `audio` 为 `false`. 如果你想捕获整个桌面的 audio 和 video,你可以设置 `chromeMediaSource` 为 `"screen"` ,和 `audio` 为 `true`. 当使用这个方法的时候,不可以指定一个 `chromeMediaSourceId`. ## 方法 `desktopCapturer` 模块有如下方法: ### `desktopCapturer.getSources(options, callback)` * `options` Object * `types` Array - 一个 String 数组,列出了可以捕获的桌面资源类型, 可用类型为 `screen` 和 `window`. * `thumbnailSize` Object (可选) - 建议缩略可被缩放的 size, 默认为 `{width: 150, height: 150}`. * `callback` Function 发起一个请求,获取所有桌面资源,当请求完成的时候使用 `callback(error, sources)` 调用 `callback` . `sources` 是一个 `Source` 对象数组, 每个 `Source` 表示了一个捕获的屏幕或单独窗口,并且有如下属性 : * `id` String - 在 `navigator.webkitGetUserMedia` 中使用的捕获窗口或屏幕的 id . 格式为 `window:XX` 祸 `screen:XX`,`XX` 是一个随机数. * `name` String - 捕获窗口或屏幕的描述名 . 如果资源为屏幕,名字为 `Entire Screen` 或 `Screen `; 如果资源为窗口, 名字为窗口的标题. * `thumbnail` [NativeImage](NativeImage.md) - 缩略图. **注意:** 不能保证 `source.thumbnail` 的 size 和 `options` 中的 `thumnbailSize` 一直一致. 它也取决于屏幕或窗口的缩放比例.
';

在渲染进程(网页)内可用的模块

最后更新于:2022-04-01 20:50:09

# 在渲染进程(网页)内可用的模块
';