找回密码
 注册
搜索
系统gho:最纯净好用系统下载站投放广告、加入VIP会员,请联系 微信:wuyouceo
查看: 89|回复: 6

办公软件WPS的JSA中获取窗口程序名

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
办公软件WPS的表格:通过ExecuteExcel4Macro调用WinAPI实现


获取鼠标指向窗口的程序文件名:
  1. function 鼠标指向窗口所属程序测试(){
  2.         let 窗口句柄=鼠标所指窗口句柄();
  3.         let 窗口信息=获取窗口信息(窗口句柄);
  4.         console.clear();
  5.         窗口信息显示(窗口信息,"","");
  6.         let 路径程序名=窗口获取路径程序名(窗口句柄);
  7.         console.log("窗口句柄:"+窗口句柄+" 路径程序名:"+路径程序名);
  8. }

  9. function 鼠标所指窗口句柄(){        //返回窗口句柄
  10.         const 执行宏调用=ExecuteExcel4Macro;
  11.         let 鼠标指针坐标=获取鼠标位置();        //===调用函数===/
  12.         let 水平=鼠标指针坐标[0],垂直=鼠标指针坐标[1];        //鼠标指针处窗口句柄        //扩展了一个参数
  13.         let 窗口句柄=执行宏调用(`CALL("User32", "WindowFromPoint", "JJJ", ${水平},${垂直})`);
  14.         return 窗口句柄;
  15. }
  16. function 获取鼠标位置(){        //返回坐标数组[x,y]
  17.         const 执行宏调用=ExecuteExcel4Macro;
  18.         var 坐标结构=执行宏调用(`CALL("User32","GetCursorPos","1E",0)`);        //参数:4+4字节坐标结构
  19.         const 缓冲区=new ArrayBuffer(8); //8字节对应64位
  20.         const 数据操作=new DataView(缓冲区);        //操作对象
  21.         数据操作.setFloat64(0,坐标结构);        //(操作)写入64位数
  22.         let 坐标=[];
  23.         坐标[0]=数据操作.getInt32(4);        //取32位坐标x
  24.         坐标[1]=数据操作.getInt32(0);        //取32位坐标y
  25.         return 坐标;
  26. }
  27. function 获取窗口信息(窗口句柄){        //返回数组[句柄,标题,类,坐标]
  28.         let 窗口标题=获取窗口标题(窗口句柄);
  29.         let 窗口类名=获取窗口类名(窗口句柄);
  30.         let 窗口内容=获取窗口内容(窗口句柄).slice(0,32);        //前32个字符
  31.         let 窗口坐标=获取窗口坐标(窗口句柄);
  32.         return [窗口句柄,窗口标题,窗口类名,窗口内容,窗口坐标];
  33. }
  34. function 窗口信息显示(窗口信息,目录,说明){        //句柄、标题、类、坐标
  35.         let 窗口句柄=窗口信息[0],窗口标题=窗口信息[1];
  36.         let 窗口类名=窗口信息[2],编辑文本=窗口信息[3],窗口坐标=窗口信息[4];
  37.         console.log(目录+说明+"句柄:"+窗口句柄+"\t"+说明+"标题:"+窗口标题+"\t"+说明+"类名:"+窗口类名+"\t"+说明+"内容:"+编辑文本+"\t"+说明+"坐标:"+窗口坐标);
  38. }
  39. function 获取窗口标题(窗口句柄){
  40.         const 执行宏调用=ExecuteExcel4Macro;
  41.         let 窗口标题长度=执行宏调用(`CALL("User32", "GetWindowTextLengthA", "JJ", ${窗口句柄})`);
  42.         let 缓冲区大小=窗口标题长度+1,窗口标题="";
  43.         const 内存地址 = 执行宏调用(`CALL("Kernel32", "VirtualAlloc", "JJJJJ", 0, ${缓冲区大小}, ${0x3000}, 4)`);        //申请内存
  44.         let 标题长度=执行宏调用(`CALL("User32", "GetWindowTextA", "JJJJ", ${窗口句柄},${内存地址},${窗口标题长度+1})`);
  45.         if(标题长度){窗口标题=内存读取字符串(内存地址);}
  46.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  47.         return 窗口标题;
  48. }
  49. function 获取窗口类名(窗口句柄){
  50.         const 执行宏调用=ExecuteExcel4Macro;
  51.         let 缓冲区大小=256,窗口类名="";        //类名最长255
  52.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${缓冲区大小},${0x3000},4)`);        //申请内存
  53.         let 类名长度=执行宏调用(`CALL("User32","GetClassNameA","JJJJ",${窗口句柄},${内存地址},${缓冲区大小})`);
  54.         if(类名长度){窗口类名=内存读取字符串(内存地址);}
  55.         执行宏调用(`CALL("Kernel32","VirtualFree","JJJJ",${内存地址},0,${0x8000})`);        //释放内存
  56.         return 窗口类名;
  57. }
  58. function 获取窗口内容(编辑框句柄){        //一般为编辑文本框,类:Edit
  59.         const 执行宏调用=ExecuteExcel4Macro;
  60.         let 编辑框内容="",获取文本长度=0xE,获取文本=0xD;        //消息含义
  61.         var 内容长度=执行宏调用(`CALL("User32", "SendMessageA", "JJJJJ", ${编辑框句柄},${获取文本长度},0,0)`);
  62.         if(内容长度){
  63.                 let 缓冲区大小=内容长度+1;
  64.                 const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${缓冲区大小},${0x3000},4)`);        //申请内存
  65.                 var 获取结果=执行宏调用(`CALL("User32", "SendMessageA", "JJJJJ", ${编辑框句柄},${获取文本},${内容长度+1},${内存地址})`);
  66.                 编辑框内容=内存读取字符串(内存地址);
  67.                 执行宏调用(`CALL("Kernel32","VirtualFree","JJJJ",${内存地址},0,${0x8000})`);        //释放内存
  68.         }
  69.         return 编辑框内容;
  70. }
  71. function 获取窗口坐标(窗口句柄){        //返回坐标数组:左上右下
  72.         const 执行宏调用=ExecuteExcel4Macro;
  73.         let 内存地址=申请虚拟内存(16);
  74.         let 结果=执行宏调用(`CALL("User32","GetWindowRect","JJJ",${窗口句柄},${内存地址})`);
  75.         let 数组缓冲=内存读取数据(内存地址,16);
  76.         释放虚拟内存(内存地址);
  77.         let 坐标数组=缓冲转数组(数组缓冲);
  78.         return 坐标数组;
  79. }
  80. function 内存读取数据(内存地址,字节数){        //返回数组缓冲
  81.         const 执行宏调用=ExecuteExcel4Macro;
  82.         let 偏移,i,读取字节=[],读出数据;
  83.         for(偏移=i=0;偏移<字节数;i++){
  84.                 if(字节数-偏移>=4){读取字节[i]=4;偏移+=4;}
  85.                 else{if(字节数-偏移>=2){读取字节[i]=2;偏移+=2;}
  86.                 else{if(字节数-偏移==1){读取字节[i]=1;偏移++;}}}
  87.         }
  88.         const 数组缓冲=new ArrayBuffer(字节数);        //用于存储读出的数据
  89.         const 数据操作=new DataView(数组缓冲);
  90.         for(偏移=i=0;偏移<字节数;i++){        //库Kernel32.dll和NtDll.dll里都有RtlMoveMemory        //读出
  91.                 读出数据=执行宏调用(`CALL("Kernel32","RtlMoveMemory","1NJJ",${内存地址},${内存地址+偏移},${读取字节[i]})`);
  92.                 if(读取字节[i]==4){数据操作.setInt32(偏移,读出数据,true);偏移+=4;}
  93.                 else{if(读取字节[i]==2){数据操作.setInt16(偏移,读出数据,true);偏移+=2;}
  94.                 else{if(读取字节[i]==1){数据操作.setInt8(偏移,读出数据,true);偏移++;}}}
  95.         }
  96.         return 数组缓冲;        //返回
  97. }
  98. function 缓冲转数组(数组缓冲){        //返回数组[]
  99.         let 总字节=数组缓冲.byteLength;
  100.         let 组数=Math.ceil(总字节/4);
  101.         const 数据操作=new DataView(数组缓冲);
  102.         let 数组=[];
  103.         for(let i=0;i<组数;i++){
  104.                 数组[i]=数据操作.getInt32(i*4,true);
  105.         }
  106.         return 数组;
  107. }
  108. function 窗口获取路径程序名(窗口句柄){
  109.         let 进程号=获取窗口进程(窗口句柄);
  110.         let 进程句柄=打开进程(进程号);
  111.         let 进程路径程序名=获取进程路径文件名(进程句柄);
  112.         关闭进程(进程句柄);
  113.         return 进程路径程序名;
  114. }
  115. function 内存读取字符串(内存地址){        //返回字符串
  116.         const 执行宏调用=ExecuteExcel4Macro,段长度=127;
  117.         const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //内存文本字节数
  118.         let 偏移字节=0,文本字符串=分段文本='';
  119.         while(偏移字节<总字节){        //返回字符串F。        //返回超255字节时,也需要分段操作
  120.                 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  121.                 偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算字符串字节数
  122.                 文本字符串+=分段文本;
  123.         }
  124.         return 文本字符串;
  125. }
  126. function 获取窗口进程(窗口句柄){        //进程
  127.         const 执行宏调用=ExecuteExcel4Macro;
  128.         let 进程号=执行宏调用(`CALL("User32","GetWindowThreadProcessId","2JN",${窗口句柄},0)`);        //第2个参数
  129.         return 进程号;
  130. }
  131. function 打开进程(进程号){        //返回进程句柄
  132.         const 执行宏调用=ExecuteExcel4Macro;
  133.         let 进程查询=0x400,进程读取=0x10;
  134.         let 访问权限=进程查询|进程读取,不继承=0;
  135.         let 进程句柄=执行宏调用(`CALL("Kernel32","OpenProcess","JJAJ",${访问权限},${不继承},${进程号})`);
  136.         return 进程句柄;
  137. }
  138. function 关闭进程(进程句柄){
  139.         const 执行宏调用=ExecuteExcel4Macro;
  140.         let 关闭结果=执行宏调用(`CALL("Kernel32","CloseHandle","AJ",${进程句柄})`);
  141.         return 关闭结果;        //成功返回true
  142. }
  143. function 获取进程路径文件名(进程句柄){        //进程
  144.         const 执行宏调用=ExecuteExcel4Macro;
  145.         let 内存地址=申请虚拟内存(4);        //Psapi.dll或Kernel32.dll        //${内存地址}
  146.         let 路径文件名=执行宏调用(`CALL("Kernel32","QueryFullProcessImageNameA","3JJFN",${进程句柄},0,"",${内存地址})`);
  147.         释放虚拟内存(内存地址);        //内存中存的是路径文件名长度
  148.         return 路径文件名;
  149. }
  150. function 申请虚拟内存(字节数){        //返回内存地址
  151.         const 执行宏调用=ExecuteExcel4Macro;
  152.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${字节数},${0x3000},4)`);
  153.         return 内存地址;
  154. }
  155. function 释放虚拟内存(内存地址){
  156.         const 执行宏调用=ExecuteExcel4Macro;
  157.         执行宏调用(`CALL("Kernel32","VirtualFree","JJJJ",${内存地址},0,${0x8000})`);
  158. }
复制代码
中间有涉及进程号、线程号、进程句柄
发表于 1 小时前 | 显示全部楼层
我实在是看不明白程序
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层
原来这是伪代码+宏

点评

什么是伪代码?  发表于 1 小时前
回复

使用道具 举报

 楼主| 发表于 1 小时前 | 显示全部楼层

这个比较简单

打开计算器或记事本,执行测试函数:

  1. function 获取已打开计算器程序名测试(){
  2.         console.clear();
  3.         let 窗口句柄=标题查找窗口("计算器");        //计算器窗口
  4.         if(窗口句柄){
  5.                 let 类名=获取窗口类名(窗口句柄);
  6.                 let 程序名=窗口获取程序名(窗口句柄);
  7.                 console.log("窗口句柄:"+窗口句柄+" 窗口类名:"+类名+"\n程序名:"+程序名);
  8.         }else{console.log("未找到标题为“计算器”的窗口!");}
  9. }
  10. function 获取已打开记事本路径程序名测试(){
  11.         console.clear();
  12.         let 窗口句柄=类查找窗口("Notepad");        //记事本窗口
  13.         if(窗口句柄){
  14.                 let 标题=获取窗口标题(窗口句柄);
  15.                 let 路径程序名=窗口获取路径程序名(窗口句柄);
  16.                 console.log("窗口句柄:"+窗口句柄+" 窗口标题:"+标题+"\n路径程序名:"+路径程序名);
  17.         }else{console.log("未找到类为“Notepad”的窗口!");}
  18. }
复制代码


用到的函数:
  1. function 标题查找窗口(标题){return 查找窗口(标题,0);}
  2. function 类查找窗口(类){return 查找窗口(0,类);}
  3. function 查找窗口(标题,类){        //返回句柄
  4.         const 执行宏调用=ExecuteExcel4Macro;
  5.         var 窗口句柄;
  6.         if(!标题){        //标题为0               
  7.                 if(!类){        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JJJ",0,0)`);        //类为0
  8.                 }else{        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JFJ","${类}",0)`);}
  9.         }else{
  10.                 if(!类){        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JJF",0,"${标题}")`);        //类为0
  11.                 }else{        窗口句柄=执行宏调用(`CALL("User32","FindWindowA","JFF","${类}","${标题}")`);}
  12.         }
  13.         return 窗口句柄;
  14. }
  15. function 获取窗口标题(窗口句柄){
  16.         const 执行宏调用=ExecuteExcel4Macro;
  17.         let 窗口标题长度=执行宏调用(`CALL("User32", "GetWindowTextLengthA", "JJ", ${窗口句柄})`);
  18.         let 缓冲区大小=窗口标题长度+1,窗口标题="";
  19.         const 内存地址 = 执行宏调用(`CALL("Kernel32", "VirtualAlloc", "JJJJJ", 0, ${缓冲区大小}, ${0x3000}, 4)`);        //申请内存
  20.         let 标题长度=执行宏调用(`CALL("User32", "GetWindowTextA", "JJJJ", ${窗口句柄},${内存地址},${窗口标题长度+1})`);
  21.         if(标题长度){窗口标题=内存读取字符串(内存地址);}
  22.         执行宏调用(`CALL("Kernel32", "VirtualFree", "JJJJ", ${内存地址}, 0, ${0x8000})`);        //释放内存
  23.         return 窗口标题;
  24. }
  25. function 获取窗口类名(窗口句柄){
  26.         const 执行宏调用=ExecuteExcel4Macro;
  27.         let 缓冲区大小=256,窗口类名="";        //类名最长255
  28.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${缓冲区大小},${0x3000},4)`);        //申请内存
  29.         let 类名长度=执行宏调用(`CALL("User32","GetClassNameA","JJJJ",${窗口句柄},${内存地址},${缓冲区大小})`);
  30.         if(类名长度){窗口类名=内存读取字符串(内存地址);}
  31.         执行宏调用(`CALL("Kernel32","VirtualFree","JJJJ",${内存地址},0,${0x8000})`);        //释放内存
  32.         return 窗口类名;
  33. }
  34. function 窗口获取程序名(窗口句柄){
  35.         let 进程号=获取窗口进程(窗口句柄);
  36.         let 进程句柄=打开进程(进程号);
  37.         let 进程路径程序名=获取进程路径文件名(进程句柄);
  38.         let 程序名=进程路径程序名.split('\\').pop();
  39.         关闭进程(进程句柄);
  40.         return 程序名;
  41. }
  42. function 窗口获取路径程序名(窗口句柄){
  43.         let 进程号=获取窗口进程(窗口句柄);
  44.         let 进程句柄=打开进程(进程号);
  45.         let 进程路径程序名=获取进程路径文件名(进程句柄);
  46.         关闭进程(进程句柄);
  47.         return 进程路径程序名;
  48. }
  49. function 内存读取字符串(内存地址){        //返回字符串
  50.         const 执行宏调用=ExecuteExcel4Macro,段长度=127;
  51.         const 总字节=执行宏调用(`CALL("Kernel32","lstrlenA","JJ",${内存地址})`);        //内存文本字节数
  52.         let 偏移字节=0,文本字符串=分段文本='';
  53.         while(偏移字节<总字节){        //返回字符串F。        //返回超255字节时,也需要分段操作
  54.                 分段文本=执行宏调用(`CALL("Kernel32","lstrcpynW","FFJJ","",${内存地址+偏移字节},${段长度})`);
  55.                 偏移字节+=分段文本.replace(/[^\x00-\xff]/g,'xx').length;        //计算字符串字节数
  56.                 文本字符串+=分段文本;
  57.         }
  58.         return 文本字符串;
  59. }
  60. function 获取窗口进程(窗口句柄){        //进程
  61.         const 执行宏调用=ExecuteExcel4Macro;
  62.         let 进程号=执行宏调用(`CALL("User32","GetWindowThreadProcessId","2JN",${窗口句柄},0)`);        //第2个参数
  63.         return 进程号;
  64. }
  65. function 打开进程(进程号){        //返回进程句柄
  66.         const 执行宏调用=ExecuteExcel4Macro;
  67.         let 进程查询=0x400,进程读取=0x10;
  68.         let 访问权限=进程查询|进程读取,不继承=0;
  69.         let 进程句柄=执行宏调用(`CALL("Kernel32","OpenProcess","JJAJ",${访问权限},${不继承},${进程号})`);
  70.         return 进程句柄;
  71. }
  72. function 关闭进程(进程句柄){
  73.         const 执行宏调用=ExecuteExcel4Macro;
  74.         let 关闭结果=执行宏调用(`CALL("Kernel32","CloseHandle","AJ",${进程句柄})`);
  75.         return 关闭结果;        //成功返回true
  76. }
  77. function 获取进程路径文件名(进程句柄){        //进程
  78.         const 执行宏调用=ExecuteExcel4Macro;
  79.         let 内存地址=申请虚拟内存(4);        //Psapi.dll或Kernel32.dll        //${内存地址}
  80.         let 路径文件名=执行宏调用(`CALL("Kernel32","QueryFullProcessImageNameA","3JJFN",${进程句柄},0,"",${内存地址})`);
  81.         释放虚拟内存(内存地址);        //内存中存的是路径文件名长度
  82.         return 路径文件名;
  83. }
  84. function 申请虚拟内存(字节数){        //返回内存地址
  85.         const 执行宏调用=ExecuteExcel4Macro;
  86.         const 内存地址=执行宏调用(`CALL("Kernel32","VirtualAlloc","JJJJJ",0,${字节数},${0x3000},4)`);
  87.         return 内存地址;
  88. }
  89. function 释放虚拟内存(内存地址){
  90.         const 执行宏调用=ExecuteExcel4Macro;
  91.         执行宏调用(`CALL("Kernel32","VirtualFree","JJJJ",${内存地址},0,${0x8000})`);
  92. }
复制代码


回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层
#在这感谢您,授人玫瑰,手有余香里快速回复#
回复

使用道具 举报

发表于 1 小时前 | 显示全部楼层
谢谢分享
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2026-7-9 18:45

Powered by Discuz! X5.0

© 2001-2026 Discuz! Team.

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