无忧启动论坛

 找回密码
 注册
搜索
系统gho:最纯净好用系统下载站广告联系 微信:wuyouceo QQ:184822951
查看: 5158|回复: 7
打印 上一主题 下一主题

[原创] 一个可以直接调用任意dll导出函数的微型js引擎

[复制链接]
跳转到指定楼层
1#
发表于 2020-11-1 15:41:04 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
总所周知,windows命令行工具有很多地方不够完善,而很多功能在dll中(win32 api)被实现,但是你没法轻易的在脚本/批处理中调用
最坑的是需要跨多个脚本,一会batch,一会vbs,过一会又要powershell(必须承认pwsh还是很强的,但是我相信大家不会为了一点小功能去开pwsh的)
当然有人可能会提rundll32,不过它只能适用于特定形式导出函数(极少数),仍然有相当数量的函数是没法这样调用的。。
当然我们可以专门整一个软件去实现这些缺失的功能,这对于正经的大项目,这个方法是合适的,但是对于短平快的脚本来说,这就有点大炮打蚊子的意思了(另一个原因是体积大了,不需要的功能太多了,而需要的可能也不一定覆盖完,毕竟每个人需求是不一样的)。


这就是我做这个工具的原因
简单来说就是整了一个c编译器到js解释器里去。
但是方便之处在于它不是只能编译到文件然后执行(但也可以生成exe dll),
而是允许直接在内存中运行,甚至可以在js中直接调用导出的函数(当然,对参数及返回类型有一定的限定,windows api要包装一层),
只要架构相同,就可以直接加载对应dll里的函数(c++的类除外,这个要折腾就复杂了)。

举个简单的栗子,这里用最基础的MessageBoxW举例(请不要使用A系列函数,有乱码的问题)
  1. // 先导入编译器类
  2. import { Compiler } from "builtin:c";
  3. // 然后初始化编译器类
  4. const compiler = new Compiler("memory");
  5. // 链接到user32以使用MessageBoxW函数
  6. compiler.link("user32");
  7. // 下面就插入一段c片段以包装这个函数(主要是调用约定的问题)
  8. // 一定要用String.raw``这样的形式包裹代码,不然里面的转义会破坏解析器
  9. compiler.compile(String.raw`
  10. // 记得启用 UNICODE 支持,由于技术限制,不支持 ANSI 文本字面量(特指中文),虽然这里没有用到
  11. #define UNICODE
  12. // 加上这个以加快编译
  13. #define WIN32_LEAN_AND_MEAN
  14. // 然后就要导入 windows.h 头文件,这个已经附带在包里了,不需要额外准备
  15. #include <windows.h>
  16. // 喜闻乐见的声明函数 PCWSTR 表示宽字符串
  17. void msgbox(PCWSTR text) {
  18.   // 然后调用 windows api
  19.   MessageBox(NULL, text, L"来自 js 的弹框", 0);
  20. }
  21. `);
  22. // 接着把里面的函数重定位出来
  23. const obj = compiler.relocate({
  24.   // 具体规则看 github 页面说明
  25.   msgbox: "w"
  26. });
  27. // import.meta.url 表示文件的url,
  28. // 另外有 import.meta.main 数组可以拿到调用参数(非入口文件是拿不到的,所以还能用来区分)
  29. obj.msgbox(`地址 ${import.meta.url}`);
复制代码
(js文件需要用utf-8编码保存,所以没法使用ANSI编码的文本字面量)
如果代码中存在错误,将会在运行时产生异常(然后会终止运行),通常不要捕获这个异常,直接让它退出是正确的。


下载地址在 https://github.com/codehz/tjs/releases (linux版本是实验性支持,问题很多,请不要用)
这里有更多代码示例 https://github.com/codehz/tjs-experiment 包括如何使用第三方dll和头文件,设定dll加载路径等,这里就不一一列出

2#
发表于 2020-11-1 16:35:27 | 只看该作者
我之前玩过node的原生绑定,现在有quickjs体积缩小不少,还是有点意思的。

点评

但是node提供了很多基础功能(( 不过还是有点和windows水土不服,已经作为一次性脚本的启动速度过慢问题  详情 回复 发表于 2020-11-1 16:50
回复

使用道具 举报

3#
发表于 2020-11-1 16:37:41 | 只看该作者
诶,用zig写的?好新奇。
回复

使用道具 举报

4#
 楼主| 发表于 2020-11-1 16:50:27 | 只看该作者
kkocdko 发表于 2020-11-1 16:35
我之前玩过node的原生绑定,现在有quickjs体积缩小不少,还是有点意思的。

但是node提供了很多基础功能((
不过还是有点和windows水土不服,以及作为一次性脚本的启动速度过慢问题
回复

使用道具 举报

5#
发表于 2020-11-1 19:17:38 | 只看该作者
回复

使用道具 举报

6#
发表于 2020-11-1 20:19:15 | 只看该作者
winapiexec
https://rammichael.com/winapiexec

calldll
http://www.ltr-data.se/opencode.html
http://www.ltr-data.se/files/calldll.zip
http://www.ltr-data.se/files/win64/calldll64.zip

RundllEx
忘记出处了, 直接提供: RundllEx.zip (72.47 KB, 下载次数: 6)
PS: 非原文件, 略微汉化了下

点评

嗯,这些是很不错,能在不少场景解决问题,但是和我这个还是有点区别的, 考虑到有以下几个问题: 1. 部分api需要上下文,比如句柄,也就是说需要连续的一串调用才能实现功能,而显然句柄脱离的进程上下文是没有意  详情 回复 发表于 2020-11-1 21:03
回复

使用道具 举报

7#
 楼主| 发表于 2020-11-1 21:03:08 | 只看该作者
Bluebells 发表于 2020-11-1 20:19
winapiexec
https://rammichael.com/winapiexec

嗯,这些是很不错,能在不少场景解决问题,但是和我这个还是有点区别的,
考虑到有以下几个问题:
1. 部分api需要上下文,比如句柄,也就是说需要连续的一串调用才能实现功能,而显然句柄脱离的进程上下文是没有意义的(最简单的,列一个目录就需要一个FindFirstFileExW连续的FindNextFileExW配合最后FindClose完成)
2. 有些系统api需要使用复杂的结构体,比如NtQuerySystemInformation这类,显然也是很难在参数上编码结构体的。。
3. 回调函数,显然不可能把函数编码到参数里
回复

使用道具 举报

8#
发表于 2020-11-6 16:27:36 | 只看该作者
支持原创
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|Archiver|捐助支持|无忧启动 ( 闽ICP备05002490号-1 )

闽公网安备 35020302032614号

GMT+8, 2024-4-26 15:21

Powered by Discuz! X3.3

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表