xChar
·4 years ago

最近在学习 electron,因为在 Windows 上 electron 自带的 Notification 功能有点少,没法加按钮啥的。

查了一下,发现有人已经基于 NodeRT 做了 electron-windows-notifications,可以在 electron 展示原生的通知框。NodeRT 能让我们在 Node.js 中使用 Windows Runtime API。

然后兴高采烈的执行 yarn add electron-windows-notifications, 结果报错了:

[4/4] Building fresh packages...
[1/5] ⠈ @nodert-win10-au/windows.applicationmodel
[2/5] ⠁ @nodert-win10-au/windows.data.xml.dom
[3/5] ⠁ @nodert-win10-au/windows.foundation
[4/5] ⠁ @nodert-win10-au/windows.ui.notifications
error SECRETPATH\node_modules\@nodert-win10-au\windows.foundation: Command failed.
Exit code: 1
Command: node-gyp rebuild
Arguments:
Directory: SECRETPATH\node_modules\@nodert-win10-au\windows.foundation
Output:
...
[SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\build\binding.vcxproj]
  _nodert_generated.cpp
  NodeRtUtils.cpp
  OpaqueWrapper.cpp
  CollectionsConverterUtils.cpp
SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\nodertutils.cpp : fatal error C1107: 未能找到程序集“Windows.winmd”: 请使用 /AI 或通过设置 LIBPATH 环境变量指定程序集搜索路径 [SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\build\binding.vcxproj]
SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\_nodert_generated.cpp : fatal error C1107: 未能找到程序集“Windows.winmd”: 请使用 /AI 或通过设置 LIBPATH 环境变量指定程序集搜索路径 [SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\build\binding.vcxproj]
  win_delay_load_hook.cc
NPMPATH\node_modules\node-gyp\src\win_delay_load_hook.cc : fatal error C1107: 未能找到程序集“Windows.winmd”: 请使用 /AI 或通过设置 LIBPATH 环境变量指定程序集搜索路径 [SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\build\binding.vcxproj]
SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\opaquewrapper.cpp : fatal error C1107: 未能找到程序集“Windows.winmd”: 请使用 /AI 或通过设置 LIBPATH 环境变量指定程序集搜索路径 [SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\build\binding.vcxproj]
SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\collectionsconverterutils.cpp : fatal error C1107: 未能找到程序集“Windows.winmd”: 请使用 /AI 或通过设置 LIBPATH 环境变量指定程序集搜索路径 [SECRETPATH\node_modules\@nodert-win10-au\windows.foundation\build\binding.vcxproj]
gyp ERR! build error

啊,这熟悉的 msvc 工具链报错。错误原因是 fatal error C1107: 未能找到程序集“Windows.winmd”,提示说可以用 LIBPATH 设置这个文件的位置。
使用 listary 查了一下本机的 Windows.winmd 的 位置,然后就开始了第一次的错误尝试,设置了 LIBPATH,依然报错。

想想以前使用 VS 的时候,需要在项目中配置一下引用的库的位置才能正确编译,所以这很有可能还是找不到库的位置所以报的错。中间的摸索过程就不写了,直接写怎么解决。

配置 node-gyp

因为之前装 node-sass 的时候接触过 node-gyp,所以现在第一件事就是要确保 node-gyp 能使用。

查看 node-gyp 的仓库 README,发现有教程: Installation On Windows

强烈建议去看原教程后再看本教程。
强烈建议去看原教程后再看本教程。
强烈建议去看原教程后再看本教程。

首先需要安装 Python,如果你本地没有,最简单的方法就是从微软商店直接安装,直接打开 Microsoft Store,搜索安装即可。
Python Microsoft Store package

node-gyp 支持以下这几个 Python 版本:v2.7, v3.5, v3.6, v3.7, v3.8。

方案 1(个人不推荐,可能会出现自己不可控制的局面)

使用 windows-build-tools 来自动配置 MsBuild 和 Python 环境。

打开一个有管理员权限的 CMD 或者 PowerShell 终端,执行:npm install --global --production windows-build-tools,等待完成即可。

方案 2

手动安装:

  1. 安装 Visual C++ Build 环境: Visual Studio Build Tools (安装组件时勾选 "Visual C++ build tools") 或者 Visual Studio 2017 Community (安装组件时勾选 "Desktop development with C++")
  2. 打开 cmd, 执行:npm config set msvs_version 2017

如果你的程序还需要运行在其他的处理器平台上,记得安装组件的时候也要勾上对应的。比如 ARM64 平台的,要选择:"Visual C++ compilers and libraries for ARM64" 和 "Visual C++ ATL for ARM64" 两个组件。

如何确定自己的 node-gyp 环境安装好了呢?
以下包随便安装一个就行了,安装成功则说明 node-gyp 环境已经好了:

  • bson
  • bufferutil
  • kerberos
  • node-sass
  • sqlite3
  • phantomjs

解决找不到 Windows.winmd 文件

其实这个问题就是代码的问题,根据这个 issue 中的描述,当前版本的 NodeRT 只会去扫描 C:\Program Files (x86)\Windows Kits\10\UnionMetadata 路径下的 .winmd 文件,硬编码了依赖库目录(不过也说得通)。

所以解决方案就是,把你的 Windows.winmd 文件放到这个文件夹下就行了,默认安装的 Windows 10 SDK 应该都在这个文件夹下的一个个子文件夹,直接把对应版本的 Windows.winmd 挪出来就行。

比如说我就把 C:\Program Files (x86)\Windows Kits\10\UnionMetadata\10.0.19041.0\Windows.winmd 这个文件往上移动了一级,也就是移动到了 .. 文件夹。现在再去安装,就已经可以了。


从此以后,遇到打包 Native 的场景,我再也不怕了!

安装成功


2020/08/24 后记

electron-windows-notifications 确实 8 太行啊,简单的 toast 写上去倒是可以弹通知,加了 actions 之后就展示不出来通知了。

而且这个库也很久没更新了,依赖的 NodeRT 的版本都很久远了,所以现在使用 node-notifier,这个包在 Windows 下会使用一个编译好的程序:SnoreToast,通过调用这个 Native 程序来显示通知。

Loading comments...