写在最前面的话
公司有个需求,就是在 Electron 运行的时候,调用系统的一部分 Win32 API。我的方向是前端,并不是很懂 Win32 API,因此只需要给出可以供其他同事使用的地方就行了。
在 Windows 上搞 Node.js 开发,一定要装好各种构建工具。如果不想装那个巨大的 Visual Studio 的话,可以看一下 这里。但由于某些众所周知的原因,身在大陆的同学们会很不愉快:不管是文中的哪个选项,都会卡在 Visual C++ Build Tools 的安装上。主要是微软这智障不提供离线安装包了。我用 VisualCppBuildTools_Full.exe /layout
把用于离线安装的文件下了下来并打了个压缩包,目前的版本是 2015,如果你遇到了同样的问题,并且信得过我,可以从 这里 下载离线安装的版本。(至于为什么不用国内的网盘,是怕由于某些原因资源突然丢失。被墙了至少比被删了要好。)
md5: 012653fc84a7d59c7297d5215e7bdd75
sha1: 58a897505090736b9a8ba229849891c37730a438
win32-api 项目
在 GitHub 上有一个叫 win32-api 的项目,虽然这个项目的 Star 比较少,但也比较简单,而且还在持续更新。它是对 ffi 项目的一个简单封装,里面包含了 User32
、Kernel32
、Comctl32
三个 dll 中的函数。看了一眼 Demo,是修改计算器程序的标题,看起来跟纯正的 C 代码长的还挺像,至少比 ffi 要好用。
在 Node.js 中实践
npm init
npm install --save win32-api
至于为什么不用 yarn,因为 yarn 会报错,说里面的某个库不兼容 win32 平台……WTF?!
然后再写一个简单的 js 文件,把样例复制过来,就可以从 Node.js 环境中调用这个啦!
如果在编译的时候出现了什么错误,一定是因为 Visual C++ Build Tools 没装好(不是 Build Tools,而是 Visual C++ Build Tools)。请确保它已经安装成功。
在 Electron 中实践
然后我尝试从 Electron 里面调用。
function createWindow() {
win = new BrowserWindow({
acceptFirstMouse: true
})
win.on('closed', () => {
win = null
})
try {
// 这个函数是刚才的样例代码
changeWindowTitle()
} catch (e) {
console.log(e)
}
}
然后提示 Error: A dynamic link library (DLL) initialization routine failed.
。经过多方搜索,发现需要在 npm install
之后还需要再执行一遍 electron-rebuild
,以构建适合 Electron 的文件。于是执行如下代码:
npm install --save electron-rebuild
.\node_modules\.bin\electron-rebuild
electron index.js
错误提示如下:
Error: The module '\\?\C:\Users\rexfg\Desktop\node-win32-test\node_modules\ref\build\Release\binding.node'
was compiled against a different Node.js version using
NODE_MODULE_VERSION 57. This version of Node.js requires
NODE_MODULE_VERSION 53. Please try re-compiling or re-installing
the module (for instance, using `npm rebuild` or`npm install`).
为了这问题我还跑去 electron-rebuild 项目发了一个 Issue,后来才发现是我本地 Electron 版本(v1.8.1)和全局(v1.6.11)不一样,把全局的 Electron 升个级就可以了。
题外话
win32-api
中给出的样例是寻找 calc.exe
的窗口并修改其标题,但由于 Windows 10 中的计算器已经是 UWP 程序,无法再调用 Win32 API 来修改标题,因此我用的是初中的时候写的 VB 程序来测试,在下图可以看到中间的窗口标题已经被改掉了:
Well done!
版权声明:除文章开头有特殊声明的情况外,所有文章均可在遵从 CC BY 4.0 协议的情况下转载。