找回密码
 注册
搜索
[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
查看: 798|回复: 7

[转载代码] 在办公软件WPS的JSA中模拟键盘输入

[复制链接]
发表于 2026-4-26 23:12:03 | 显示全部楼层 |阅读模式
办公软件WPS的表格:通过ExecuteExcel4Macro调用WinAPI实现

测试与调用函数:        //打开记事本,输入内容
  1. function 找到记事本窗口键盘输入测试(){        //记事本编辑框中输入内容
  2.         console.clear();
  3.         const 执行宏调用=ExecuteExcel4Macro;
  4.        
  5.         let 记事本类="Notepad";        //找到那个打开的记事本窗口
  6.         var 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  7.         console.log("记事本句柄:"+记事本句柄);
  8.         if(!记事本句柄){
  9.                 let 记事本进程句柄=执行宏调用(`CALL("Shell32","ShellExecuteA","JJFFJJJ",0,"open","notepad",0,0,1)`);
  10.                 console.log("记事本进程句柄:"+记事本进程句柄);
  11.                 alert("等待,确定后向记事本写入信息");
  12.                 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  13.                 console.log("记事本句柄:"+记事本句柄);
  14.         }
  15.     执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${记事本句柄})`);        //前置
  16.        
  17.         let 字符串="BatHome.Net";        //批处理之家论坛网址,作为填写内容
  18.         let 字符数组=字符串.split(''),按键数组=[];
  19.         for(let i=0;i<字符串.length;i++){
  20.                 var 字符=字符数组[i];
  21.                 if(字符>='a' && 字符<='z'){字符=字符.toUpperCase();}
  22.                 按键数组[i]=键盘操作对象(字符);
  23.         }
  24.         操作键盘(按键数组);        /*****键盘操作*****/
  25. }

  26. function 操作键盘(操作数组){
  27.         let 序号=0,键盘数组=[];
  28.         if(Array.isArray(操作数组)){
  29.                 for(let i=0;i<操作数组.length;i++){
  30.                         if(Array.isArray(操作数组[i])){
  31.                                 for(let j=0;j<操作数组[i].length;j++){
  32.                                         键盘数组[序号]=操作数组[i][j];序号++;
  33.                                 }
  34.                         }else{键盘数组[序号]=操作数组[i];序号++;}
  35.                 }
  36.         }else{键盘数组[序号]=操作数组;}
  37.         let 操作组数=键盘数组.length;
  38.         let 结构字节数=对象字节数(键盘数组[0]);        /*****计算结构对象字节数*****/
  39.         let 总字节=结构字节数*操作组数;
  40.        
  41.         const 数组缓冲=new ArrayBuffer(总字节);        //操作对象数组写入缓冲
  42.         for(let i=0;i<操作组数;i++){
  43.                 结构对象填入数组缓冲(数组缓冲,i*结构字节数,键盘数组[i]);        /*****对象转数组缓冲*****/
  44.         }
  45.         const 执行宏调用=ExecuteExcel4Macro;        //申请内存
  46.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${总字节},${0x3000},4)`);
  47.         数据写入内存(内存地址,数组缓冲,总字节);        /*****写入键盘操作结构*****/        //执行键盘操作
  48.         键盘操作结果=执行宏调用(`CALL("User32","SendInput","JJJJ",${操作组数},${内存地址},${结构字节数})`);
  49.         if(!键盘操作结果){console.log("错误代码:"+执行宏调用(`CALL("Kernel32","GetLastError","I")`));}
  50.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  51. }
  52. function 键盘操作对象(键码){
  53.         class 键盘操作 {        //类
  54.                 constructor(按键,动作){        //类的构造方法,用于构造属性
  55.                         this.输入类型1 = [4,1],        //键盘1        //字节数,数据
  56.                         this.虚拟键码2 = [4,按键],        //同ASCII码
  57.                         this.键扫描码3 = [4,0],
  58.                         this.输入操作4 = [4,动作],        //按键弹起2        启用扫描码8
  59.                         this.时间戳值5 = [4,0],        //系统确定
  60.                         this.扩展信息6 = [4,0],
  61.                         this.数据填充0 = [4,0]        //都是4*7=28字节,不足部分补足
  62.                 }
  63.         };
  64.         if(键码>='A'&&键码<='Z'){键码=键码.charCodeAt(0);}
  65.         if(键码=='.'){键码=0xBE;}
  66.         let 键盘对象 = new 键盘操作(键码,4|2);        //统一码0x4|2键弹起
  67.         return 键盘对象;
  68. }
  69. function 对象字节数(结构对象){
  70.         let 对象数据字节数=0;
  71.         for (let 属性名 in 结构对象) {
  72.                 if (结构对象.hasOwnProperty(属性名)) {
  73.                         对象数据字节数+=结构对象[属性名][0];        //累加字节数
  74.                 }
  75.         }
  76.         return 对象数据字节数;
  77. }
  78. function 结构对象填入数组缓冲(数组缓冲,偏移,结构对象){
  79.         const 数据操作=new DataView(数组缓冲);
  80.         let 字节数,待填数据;
  81.         for (let 属性名 in 结构对象) {
  82.                 if (结构对象.hasOwnProperty(属性名)) {
  83.                         字节数=结构对象[属性名][0],待填数据=结构对象[属性名][1];
  84.                         if(字节数==4){数据操作.setInt32(偏移,待填数据,true);}        //小端序
  85.                         else{if(字节数==2){数据操作.setInt32(偏移,待填数据,true);}
  86.                         else{if(字节数==1){数据操作.setInt32(偏移,待填数据,true);}}}
  87.                         偏移+=字节数;
  88.                 }
  89.         }
  90. }
  91. function 数据写入内存(内存地址,数组缓冲,字节数){
  92.         const 数据操作=new DataView(数组缓冲);
  93.         let 偏移=i=0,待写数据=[],写入字节=[];
  94.         while(字节数>偏移){
  95.                 if(字节数-偏移>=4){待写数据[i]=数据操作.getInt32(偏移,true);写入字节[i]=4;i++;偏移+=4;}
  96.                 else{if(字节数-偏移>=2){待写数据[i]=数据操作.getInt16(偏移,true);写入字节[i]=2;i++;偏移+=2;}
  97.                 else{if(字节数-偏移==1){待写数据[i]=数据操作.getInt8(偏移,true);写入字节[i]=1;i++;偏移++;}}}
  98.         }
  99.         const 执行宏调用=ExecuteExcel4Macro;
  100.         for(偏移=i=0;i<写入字节.length;i++){        //写入
  101.                 执行宏调用(`CALL("Kernel32","RtlMoveMemory","2JNJ",${内存地址+偏移},${待写数据[i]},${写入字节[i]})`);
  102.                 偏移+=写入字节[i];
  103.         }
  104. }
复制代码

评分

参与人数 1技术 +1 收起 理由
老刘1号 + 1 感谢分享

查看全部评分

 楼主| 发表于 2026-4-27 11:15:07 | 显示全部楼层
通过SendMessage向文本编辑区填入内容:
  1. function 记事本窗口发送文本测试(){        //记事本编辑框中内容
  2.         console.clear();
  3.         const 执行宏调用=ExecuteExcel4Macro;
  4.         
  5.         //找到打开的记事本窗口,没有则打开一个新记事本
  6.         let 记事本类="Notepad";
  7.         var 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  8.         console.log("记事本句柄:"+记事本句柄);
  9.         if(!记事本句柄){
  10.                 let 记事本进程句柄=执行宏调用(`CALL("Shell32","ShellExecuteA","JJFFJJJ",0,"open","notepad",0,0,1)`);
  11.                 console.log("记事本进程句柄:"+记事本进程句柄);
  12.                 alert("等待,确定后向记事本写入信息");        //弹窗提示
  13.                 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  14.                 console.log("记事本句柄:"+记事本句柄);
  15.         }
  16.             执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${记事本句柄})`);        //前置
  17.         
  18.         //定位到记事本的编辑输入区
  19.         let 编辑框类="Edit";
  20.         let 编辑框句柄=执行宏调用(`CALL("User32","FindWindowExA","JJJFJ",${记事本句柄},0,"${编辑框类}",0)`);
  21.         
  22.         //通过发送消息,向记事本写入文本
  23.         let 设置文本=0xC,字符串="BatHome.Net";        //批处理之家论坛网址,作为内容
  24.         var 设置文本框内容=执行宏调用(`CALL("User32", "SendMessageA", "JJJJF", ${编辑框句柄},${设置文本},0,"${字符串}")`);
  25. }
复制代码
 楼主| 发表于 2026-5-3 11:11:31 | 显示全部楼层

模拟键盘输入应用:截屏

截取全屏和当前窗口函数:

  1. function 截取全屏测试(){        //截屏键PrintScreen
  2.         let 按下=0,扩展=1,松开=2;
  3.         let 截屏键码=0x2C,截屏扫描码=0x37;
  4.         键盘事件(截屏键码,截屏扫描码,按下|扩展);        //按下PrintScreen
  5.         键盘事件(截屏键码,截屏扫描码,松开|扩展);        //松开PrintScreen
  6. }
  7. function 截屏当前窗口测试(){        //当前窗口 Alt + PrintScreen
  8.         let 按下=0,扩展=1,松开=2;        //Alt0x12,左Alt0xA4
  9.         let 修改键码=0x12,截屏键码=0x2C,截屏扫描码=0x37;
  10.         键盘事件(修改键码,0,按下);        //按下Alt
  11.         键盘事件(截屏键码,截屏扫描码,按下|扩展);        //按下PrintScreen
  12.         键盘事件(截屏键码,截屏扫描码,松开|扩展);        //松开PrintScreen
  13.         键盘事件(修改键码,0,松开);        //松开Alt
  14. }
  15. function 键盘事件(虚拟键码,扫描键码,键标志){
  16.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  17.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  18. }
复制代码
 楼主| 发表于 2026-5-3 11:16:52 | 显示全部楼层

模拟键盘输入应用:打开运行对话框

打开运行对话框:Win + R
  1. function 打开运行对话框键盘测试(){        //快捷键 Win + R
  2.         let 按下=0,扩展=1,松开=2;
  3.         //键盘事件(虚拟键码,扫描键码,键标志);
  4.         let 左窗口=0x5B,运行=0x52;
  5.         键盘事件(左窗口,左窗口,按下|扩展);        //按下LWin
  6.         键盘事件(运行,0,按下);        //按下R
  7.         键盘事件(运行,0,松开);        //松开R
  8.         键盘事件(左窗口,左窗口,松开|扩展);        //松开LWin        //合成 LWin + R 运行
  9. }
  10. function 键盘事件(虚拟键码,扫描键码,键标志){
  11.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  12.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  13. }
复制代码
 楼主| 发表于 2026-5-3 11:19:36 | 显示全部楼层

模拟键盘输入应用:打开/关闭小键盘数字指示灯

  1. function 关闭数字灯(){
  2.         let 数字键码=0x90;
  3.         let 数字灯状态=获取按键状态(数字键码);        //关闭0
  4.         if(数字灯状态){
  5.                 let 数字扫描码=0x45,按下=0,扩展=1,松开=2;
  6.                 键盘事件(数字键码,数字扫描码,按下|扩展);        //按下NumLock
  7.                 键盘事件(数字键码,数字扫描码,松开|扩展);        //松开NumLock
  8.         }
  9. }
  10. function 打开数字灯(){
  11.         let 数字键码=0x90;
  12.         let 数字灯状态=获取按键状态(数字键码);        //打开1
  13.         if(!数字灯状态){
  14.                 let 数字扫描码=0x45,按下=0,扩展=1,松开=2;
  15.                 键盘事件(数字键码,数字扫描码,按下|扩展);        //按下NumLock
  16.                 键盘事件(数字键码,数字扫描码,松开|扩展);        //松开NumLock
  17.         }
  18. }
  19. function 获取按键状态(键盘码){
  20.         const 执行宏调用=ExecuteExcel4Macro;
  21.         let 状态=执行宏调用(`CALL("User32","GetKeyState","IJ",${键盘码})`);
  22.         return 状态;
  23. }
  24. function 键盘事件(虚拟键码,扫描键码,键标志){
  25.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  26.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  27. }
复制代码
 楼主| 发表于 2026-5-3 11:58:52 | 显示全部楼层
本帖最后由 cutebe 于 2026-5-3 12:00 编辑
  1. function 显示桌面键盘测试(){        //快捷键 Win + D
  2.         let 按下=0,扩展=1,松开=2;
  3.         let 左窗口=0x5B,按键D='D'.charCodeAt();
  4.         键盘事件(左窗口,左窗口,按下|扩展);        //按下LWin
  5.         键盘事件(按键D,0,按下);        //按下D
  6.         键盘事件(按键D,0,松开);        //松开D
  7.         键盘事件(左窗口,左窗口,松开|扩展);        //松开LWin        //合成 LWin + D
  8. }
  9. function 键盘事件(虚拟键码,扫描键码,键标志){
  10.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键才用扫描码
  11.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  12. }
复制代码


扩展按键虚拟键码扫描码说明
----- --------------------
系统关机0xE05E
系统睡眠0xE05F
系统唤醒0xE063
键盘 PrintScreen 键0x2C0xE037
键盘 Pause 键0x130xE046
键盘 Insert 键0x2D0xE052
键盘 Home 键0x240xE047
键盘 PageUp 键0x210xE049
键盘 Delete 键0x2E0xE053
键盘 End 键0x230xE04F
键盘 PageDown 键0x220xE051
键盘向右→键0x270xE04D
键盘向左←键0x250xE04B
键盘向下↓键0x280xE050
键盘向上↑键0x260xE048
小键盘 Num Lock 键0x900xE045
小键盘 /0x6F0xE035
小键盘 ENTER 键0xE01C
键盘应用程序键0x5D0xE05D菜单键VK_APPS,在右Win和右Ctrl之间
键盘电源键0xE05E
键盘 左Win 键0x5B0xE05B
键盘 右Ctrl 键0xA30xE01DVK_RCONTROL
键盘 右Alt 键0xA50xE038VK_RMENU
键盘 右Win 键0x5C0xE05C
扫描下一个曲目0xE019
扫描上一个曲目0xE010
停止0xE024
播放/暂停0xE022
静音0xE020
音量增大0xE030
音量减小0xE02E
AL 使用者控制配置0xE06D
AL 电子邮件阅读器0xE06C
AL 计算器0xE021
AL 本地计算机浏览器0xE06B
AC 搜索0xE065
AC 主页0xE032
AC 返回0xE06A
AC 向前0xE069
AC 停止0xE068
AC 刷新0xE067
AC 书签0xE066
 楼主| 发表于 2026-5-3 23:40:55 | 显示全部楼层

模拟键盘输入测试:内码转文字

  1. function 文字模拟数字按键输入测试(){
  2.         let 我=52946,爱=45230,你=50403;
  3.         let C=0x43,N=0x4E;
  4.         let 输出字符串=[我,爱,你,C,N];
  5.         for(let i=0;i<输出字符串.length;i++){
  6.                 组合数码键入对应文字(输出字符串[i]);
  7.         }
  8.         //光标放在此处:
  9. }
  10. function 组合数码键入对应文字(数字码){        //数字码为内码
  11.         let 数字串=数字码.toString();        //转数字字符串
  12.         let 按下=0,松开=2,长修码=0x12;
  13.         键盘事件(长修码,0,按下);        //按下键Alt
  14.         for(let i=0;i<数字串.length;i++){
  15.                 let 数字=数字串[i];
  16.                 let 小键盘数字码=0x30+数字.charCodeAt(0);
  17.                 let 小键盘数字扫描码=按键码转扫描码(小键盘数字码);
  18.                 键盘事件(小键盘数字码,小键盘数字扫描码,按下);
  19.                 键盘事件(小键盘数字码,小键盘数字扫描码,松开);
  20.         }
  21.         键盘事件(长修码,0,松开);        //松开键Alt
  22. }
  23. function 键盘事件(虚拟键码,扫描键码,键标志){
  24.         const 执行宏调用=ExecuteExcel4Macro;        //扫描码只需要低位,高位0xE0省略        //扩展键小键盘数字会用到扫描码
  25.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  26. }
  27. function 按键码转扫描码(按键码){        //返回扫描码
  28.         const 执行宏调用=ExecuteExcel4Macro;
  29.         let 扫描码=执行宏调用(`CALL("User32","MapVirtualKeyA","JJJ",${按键码},0)`);
  30.         return 扫描码;
  31. }
复制代码
 楼主| 发表于 2026-5-4 16:59:21 | 显示全部楼层

模拟键盘输入文字:Alt + 内码

批处理:Alt+50682,Alt+46246,Alt+49389

  1. function 记事本窗口模拟键盘输入文本测试(){        //记事本编辑框中内容
  2.         console.clear();
  3.         const 执行宏调用=ExecuteExcel4Macro;
  4.        
  5.         //找到打开的记事本窗口,没有则打开一个新记事本
  6.         let 记事本类="Notepad";
  7.         var 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  8.         console.log("记事本句柄:"+记事本句柄);
  9.         if(!记事本句柄){
  10.                 let 记事本进程句柄=执行宏调用(`CALL("Shell32","ShellExecuteA","JJFFJJJ",0,"open","notepad",0,0,1)`);
  11.                 console.log("记事本进程句柄:"+记事本进程句柄);
  12.                 alert("等待,确定后向记事本写入信息");        //弹窗提示
  13.                 记事本句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${记事本类}",0)`);
  14.                 console.log("记事本句柄:"+记事本句柄);
  15.         }
  16.        
  17.         //字符串写入内存,再按数据方式读取出来(即内码)
  18.         字符串="批处理之家 BatHome.Net";
  19.         let 内存句柄=字符串到内存(字符串);        //===写字符串===//
  20.         let 读出字符串=内存取字符串(内存句柄);
  21.         console.log(读出字符串);
  22.         let 数据数组缓冲=内存取数据(内存句柄);        //===读取数据===//
  23.         显示数组缓冲(数据数组缓冲);        //===显示数据===//
  24.         执行宏调用(`CALL("Kernel32","GlobalFree","JJ",${内存句柄})`);        //释放内存
  25.         let 文字内码=数组缓冲转文字内码数组(数据数组缓冲);
  26.         console.log("文字内码数组:"+文字内码);
  27.        
  28.         //模拟键盘按键,向记事本写入文本
  29.         执行宏调用(`CALL("User32","SetForegroundWindow","JJ",${记事本句柄})`);        //前置记事本窗口
  30.         for(let i=0;i<文字内码.length;i++){
  31.                 组合数码键入对应文字(文字内码[i]);
  32.         }        //光标放在此处:
  33. }

  34. function 数组缓冲转文字内码数组(数组缓冲){        //返回数组
  35.         const 总字节=数组缓冲.byteLength;
  36.         const 数据操作=new DataView(数组缓冲);
  37.         let 偏移=0,文字内码=[];
  38.         while(偏移<总字节){
  39.                 var 文字数码=数据操作.getUint8(偏移,true),偏移增量=1;
  40.                 if(!文字数码){break;}
  41.                 else{if(文字数码>0x80){文字数码=数据操作.getUint16(偏移),偏移增量=2;}}
  42.                 文字内码.push(文字数码);
  43.                 偏移+=偏移增量;
  44.         }
  45.         return 文字内码;
  46. }
  47. function 组合数码键入对应文字(数字码){        //数字码为内码
  48.         let 数字串=数字码.toString();        //转数字字符串
  49.         let 按下=0,松开=2,长修码=0x12;
  50.         键盘事件(长修码,0,按下);        //按下键Alt
  51.         for(let i=0;i<数字串.length;i++){
  52.                 let 数字=数字串[i];
  53.                 let 小键盘数字码=0x30+数字.charCodeAt(0);
  54.                 let 小键盘数字扫描码=按键码转扫描码(小键盘数字码);
  55.                 键盘事件(小键盘数字码,小键盘数字扫描码,按下);
  56.                 键盘事件(小键盘数字码,小键盘数字扫描码,松开);
  57.         }
  58.         键盘事件(长修码,0,松开);        //松开键Alt
  59. }
  60. function 键盘事件(虚拟键码,扫描键码,键标志){
  61.         const 执行宏调用=ExecuteExcel4Macro;        //扩展时扫描码只需要低位,高位0xE0省略        //扩展键小键盘数字会用到扫描码
  62.         执行宏调用(`CALL("User32","keybd_event","JJJJJ",${虚拟键码},${扫描键码},${键标志},0)`);
  63. }
  64. function 按键码转扫描码(按键码){        //返回扫描码
  65.         const 执行宏调用=ExecuteExcel4Macro;
  66.         let 扫描码=执行宏调用(`CALL("User32","MapVirtualKeyA","JJJ",${按键码},0)`);
  67.         return 扫描码;
  68. }
  69. function 字符串到内存(字符串){        //返回内存句柄
  70.         const 执行宏调用=ExecuteExcel4Macro;
  71.         let 分段文本=[],分段字节=[],总字节=0,段长度=127;        //可申请256字节内存,结束符1字节,汉字最长127
  72.         for(let 起始=i=0;起始<字符串.length;起始+=段长度,i++){
  73.                 分段文本.push(字符串.slice(起始,起始+段长度));
  74.                 分段字节.push(分段文本[i].replace(/[^\x00-\xff]/g,'xx').length);        //一个汉字占两个字节
  75.                 总字节+=分段字节[i];
  76.         }        //分配内存        //分配GlobalAlloc对应销毁GlobalFree        //分配GlobalAlloc对应销毁GlobalFree
  77.         const 内存句柄=执行宏调用(`CALL("Kernel32","GlobalAlloc","JJJ",${0x42},${总字节+1})`);
  78.         if(内存句柄){        //内存分配成功,然后锁写解内存。        //锁定全局内存对象,会返回其内存地址
  79.                 const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);
  80.                 for(let 偏移字节=i=0;i<分段文本.length;i++){        //字符串(JS变量)分批复制到刚申请的内存中。分批是因为有限长
  81.                         执行宏调用(`CALL("Kernel32","lstrcpynW","JJFJ",${内存地址+偏移字节},"${分段文本[i].replace(/\"/g,'\"\"')}",${分段字节[i]})`);
  82.                         偏移字节+=分段字节[i];        //返回地址J。        //字符串两个双引号解释成一个
  83.                 }
  84.                 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`);        //解锁全局内存对象,以释放资源
  85.                 return 内存句柄;
  86.         }else{console.log("未能分配内存!");}
  87. }
  88. function 内存取字符串(内存句柄){        //返回字符串
  89.         const 执行宏调用=ExecuteExcel4Macro,段长度=127;
  90.         const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);        //锁定,获取内存地址
  91.         if(内存地址){
  92.                 const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //内存文本字节数
  93.                 let 偏移字节=0,文本字符串=分段文本='';
  94.                 while(偏移字节<总字节){        //返回字符串F。        //返回超255字节时,也需要分段操作
  95.                         分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  96.                         //偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算字符串字节数
  97.                         偏移字节+=执行宏调用(`LENB("${分段文本.replace(/"/g,'x')}")`);
  98.                         文本字符串+=分段文本;
  99.                 }        //解锁全局内存对象,以释放资源
  100.                 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`);
  101.                 return 文本字符串;
  102.         }else{console.log("未找到内存地址!");}
  103. }
  104. function 内存取数据(内存句柄){        //返回数组缓冲
  105.         const 执行宏调用=ExecuteExcel4Macro;
  106.         const 总字节=执行宏调用(`CALL("Kernel32","GlobalSize","JJ",${内存句柄})`);        //内存对象空间大小
  107.         let 偏移,i,读取字节=[],读出数据;
  108.         for(偏移=i=0;偏移<总字节;i++){
  109.                 if(总字节-偏移>=4){读取字节[i]=4;偏移+=4;}
  110.                 else{if(总字节-偏移>=2){读取字节[i]=2;偏移+=2;}
  111.                 else{if(总字节-偏移==1){读取字节[i]=1;偏移++;}}}
  112.         }
  113.         const 数组缓冲=new ArrayBuffer(总字节);        //用于存储读出的数据
  114.         const 数据操作=new DataView(数组缓冲);
  115.         const 内存地址=执行宏调用(`CALL("Kernel32","GlobalLock","JJ",${内存句柄})`);
  116.         if(内存地址){        //var 文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址},${127})`);
  117.                 for(偏移=i=0;偏移<总字节;i++){        //库Kernel32.dll和NtDll.dll里都有RtlMoveMemory
  118.                         读出数据=执行宏调用(`CALL("Kernel32","RtlMoveMemory","1NJJ",${内存地址},${内存地址+偏移},${读取字节[i]})`);        //读出
  119.                         if(读取字节[i]==4){数据操作.setInt32(偏移,读出数据,true);偏移+=4;}
  120.                         else{if(读取字节[i]==2){数据操作.setInt16(偏移,读出数据,true);偏移+=2;}
  121.                         else{if(读取字节[i]==1){数据操作.setInt8(偏移,读出数据,true);偏移++;}}}
  122.                 }
  123.                 执行宏调用(`CALL("Kernel32","GlobalUnlock","JJ",${内存句柄})`);        //解锁内存对象,以释放资源
  124.                 return 数组缓冲;        //返回
  125.         }else{console.log("未找到内存地址!");}
  126. }
  127. function 显示数组缓冲(数组缓冲){
  128.         const 数据操作=new DataView(数组缓冲);
  129.         var 字节数码串=[],字符串=[],行号,四分隔,八分隔;
  130.         for(let 偏移=0;偏移<数组缓冲.byteLength;偏移++){
  131.                 var 字节数码=数据操作.getInt8(偏移);
  132.                 行号=Math.floor(偏移/16);
  133.                 if((偏移+1)%4){四分隔=''}else{四分隔=' '};
  134.                 if((偏移+1)%8){八分隔=''}else{八分隔=' '};
  135.                 if(typeof 字节数码串[行号]=="undefined"){字节数码串[行号]=''}
  136.                 var 字节高位=(字节数码>>>4&0xF).toString(16).toUpperCase(),字节低位=(字节数码&0xF).toString(16).toUpperCase();
  137.                 字节数码串[行号]+=字节高位+字节低位+" "+四分隔+八分隔;
  138.                 if(typeof 字符串[行号]=="undefined"){字符串[行号]=''}
  139.                 if(字节数码){字符串[行号]+=String.fromCharCode(字节数码);}else{字符串[行号]+=' ';}
  140.         }
  141.         for(let 行号=0;行号<字节数码串.length;行号++){
  142.                 var 十六进制行号=('000'+(行号<<4).toString(16)).slice(-4).toUpperCase();
  143.                 console.log(十六进制行号+":"+字节数码串[行号]+"\t["+字符串[行号]+"]");
  144.         }
  145. }
复制代码
您需要登录后才可以回帖 登录 | 注册

本版积分规则

Archiver|手机版|小黑屋|批处理之家 ( 渝ICP备10000708号 )

GMT+8, 2026-5-25 07:50

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

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