ACC 探测器

在FlaUI探测器源码上,改了一个ACC探测器

//MSAA 探测器
import fonts.fontAwesome;
import win.ui;
/*DSG{{*/
var winform = win.form(text="FlaUI 探测器(FlaUISpy)";left=-2;top=100;right=522;bottom=464)
winform.add(
btnCtrlParent={cls="plus";text="上级控件";left=282;top=105;right=387;bottom=129;align="left";color=8388608;dr=1;dt=1;iconColor=32768;iconStyle={align="left";font=LOGFONT(name='FontAwesome');padding={left=5}};iconText='\uF122';notify=1;textPadding={left=21};z=17};
btnHelp={cls="plus";text="教程";left=436;top=18;right=493;bottom=42;align="left";color=8388608;dr=1;dt=1;iconStyle={align="left";font=LOGFONT(h=-14;name='FontAwesome')};iconText='\uF059 ';notify=1;textPadding={left=16;bottom=1};z=21};
btnQuery={cls="plus";left=459;top=134;right=485;bottom=158;align="left";color=8388608;dr=1;dt=1;iconColor=32768;iconStyle={font=LOGFONT(name='FontAwesome')};iconText='\uF002';notify=1;textPadding={left=21};z=20};
chkCtrl={cls="checkbox";text="按 Ctrl + 移动鼠标启动探测";left=312;top=327;right=501;bottom=349;db=1;dr=1;z=15};
editCode={cls="richedit";left=77;top=165;right=494;bottom=314;db=1;dl=1;dr=1;dt=1;edge=1;hscroll=1;multiline=1;tabstop=1;vscroll=1;z=13};
editControlName={cls="edit";left=78;top=78;right=493;bottom=99;dl=1;dr=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=12};
editControlType={cls="edit";left=78;top=105;right=271;bottom=128;dl=1;dr=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=11};
editHwnd={cls="edit";left=78;top=18;right=168;bottom=41;dl=1;dt=1;edge=1;hidesel=1;multiline=1;readonly=1;tabstop=1;z=8};
editPath={cls="edit";left=78;top=48;right=495;bottom=71;dl=1;dr=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=9};
editPid={cls="edit";left=225;top=18;right=310;bottom=41;dl=1;dr=1;dt=1;edge=1;hidesel=1;readonly=1;tabstop=1;z=10};
editXPath={cls="edit";left=78;top=135;right=457;bottom=159;border=1;dl=1;dr=1;dt=1;edge=1;hidesel=1;tabstop=1;z=19};
lbControlType={cls="static";text="ControlType:";left=3;top=106;right=73;bottom=123;align="right";dl=1;dt=1;z=3};
lbHwnd={cls="static";text="窗口句柄:";left=10;top=20;right=73;bottom=37;align="right";dl=1;dt=1;z=1};
lbName={cls="static";text="Name:";left=0;top=78;right=73;bottom=95;align="right";dl=1;dt=1;z=2};
lbPid={cls="static";text="进程ID:";left=174;top=19;right=221;bottom=41;align="right";dl=1;dt=1;z=4};
lbProcessInfo={cls="static";left=360;top=100;right=495;bottom=122;dr=1;dt=1;transparent=1;z=14};
plusCur={cls="plus";left=22;top=316;right=54;bottom=348;background="\.res\1.gif";db=1;dl=1;notify=1;repeat="center";z=5};
static={cls="static";text="启动文件:";left=5;top=49;right=73;bottom=66;align="right";dl=1;dt=1;z=6};
static2={cls="static";text="请拖动左侧瞄准器图标到目标控件";left=64;top=328;right=293;bottom=353;db=1;dl=1;dr=1;z=7};
static3={cls="static";text="示例代码:";left=-7;top=164;right=73;bottom=181;align="right";dl=1;dt=1;z=16};
static4={cls="static";text="XPath:";left=0;top=135;right=73;bottom=152;align="right";dl=1;dt=1;z=18}
)
/*}}*/

winform.btnHelp.skin({
    color={
        active=0xFF00FF00;
        default=0xFF000080;
        disabled=0xFF6D6D6D;
        hover=0xFFFF0000
    }
})

import string.template;
var codeTemplate = string.template();
codeTemplate.template = /***
import winex.accObject;
import winex;
import console;

for hwnd,title,threadId,processId in winex.each( "${class}", "${title}" ) {     
    var accObject = winex.accObject.fromWindow(hwnd)
    // https://learn.microsoft.com/zh-cn/windows/win32/winauto/object-roles
    if(accObject){
        accObject.takeFocus()
        var accMessage = accObject.find(role="${roleText}";name="${name}")
        if(accMessage){
            accMessage.takeFocus()
            console.log(accMessage.roleText(),accMessage.name(),accMessage.stateText());    
        } 
        
    } 
}

    
console.pause();
***/
    
var validPattern = function(str){
    if(!#str) return "";
        
    var mbs = string.match(str,"[\s\w]*:+[\s\w]*")
    if(#mbs)
        return mbs;
        
    str = string.replace(str,"(\p)","\\\1")     
    str = string.replace(str,"\x+",function(str){
        if(..string.find(str,"\d") ){
            if(..string.find(str,"[a-zA-Z]") ) return "\x+"
            return "\d+"
        }
        return str;
    } )     
    
    str = string.replace(str,"\d+","\\d+")  
    return str;
}

import winex;
import winex.accObject;
import mouse;
import process;
import process.wmi;
import win.ui.mask;
var frmMask = win.ui.mask(winform);
frmMask.bgcolor = 0xD355BA;

var ShowInspectInfo = function(ele,x,y){ 
    
    if(ele){
        if(x!==null){
            winform.uiaInspectInfo.x =  x;
        }
        else {
            x =  winform.uiaInspectInfo.x;
        }
        
        if(y!==null){
            winform.uiaInspectInfo.y =  y;
        }
        else {
            y =  winform.uiaInspectInfo.y;
        }
        
        
        if(winform.uiaInspectInfo.element!=ele){
            winform.uiaInspectInfo.element = ele;
            //ele[["$window"]] = winform.uiaInspectInfo.window;
            winform.btnCtrlParent.disabled = !winform.uiaInspectInfo.element.Parent;
            
            //var rc = ::RECT();
            //rc.float(ele.location());             
            
            //var x,y,cx,cy = ele.location(); 
            var rc = ::RECT();
            //rc.contains(x,y);
            //rc.copy(cx,cy);
            rc.ltrb(ele.location());
            frmMask.moveToRect(rc)
            
            winform.editControlType.text = ele.roleText();
            winform.editControlName.text = ele.name(); 
            
            var hwndStr = ..string.format("0x%0X",winform.uiaInspectInfo.hwnd);
            if(hwndStr!=winform.editHwnd.text ){
                winform.editHwnd.text = hwndStr;
                
                var tid,pid = win.getThreadProcessId(winform.uiaInspectInfo.hwnd);
                winform.editPid.text = pid;
                
                var prcs = process.wmi(pid);
                winform.editPath.text = prcs.CommandLine;
                //codeTemplate.$exe = fsys.getFileName(prcs.ExecutablePath);
                codeTemplate.$class =  win.getClass(winform.uiaInspectInfo.hwnd);
                codeTemplate.$title =  winex.getText(winform.uiaInspectInfo.hwnd,50);
                //codeTemplate.$classPattern = validPattern(codeTemplate.$class);
                //codeTemplate.$titlePattern = validPattern(codeTemplate.$title);
                //codeTemplate.$hwnd = hwndStr;
                codeTemplate.$roleText = ele.roleText();
                codeTemplate.$name = ele.name(); 
            }
            
            winform.editCode.text = codeTemplate.format({});
            
            /**
            var xpath,shortXPath = FlaUI.Spy.GetXPath(ele); 
            winform.editCode.text = codeTemplate.format(
                xpath = shortXPath ? ("XPath:" + xpath) : "";
                shortXPath = shortXPath ? shortXPath : xpath;
                x = x ? (x - rc.left) : (rc.width() / 2);
                y = y ? (y - rc.top) : (rc.height()/2);
            ) 
            
            winform.editXPath.text = xpath;
            winform.uiaInspectInfo.shortXPath = shortXPath; 
            **/
            
            //这个函数很卡,建议改用 aardio 提供的 win.ui.mask
            //FlaUI.DrawHighlight(ele);
        }
        else {
            //var x,y,cx,cy = ele.location(); 
            var rc = ::RECT();
            //rc.contains(x,y);
            //rc.copy(cx,cy);
            rc.ltrb(ele.location());
            frmMask.moveToRect(rc)
        } 
    } 
}

winform.plusCur.skin(
    background = { 
        active = "\.res\2.gif"; 
    }
)

import win.cur;
var hCursor = win.cur.loadfile("\.res\spy.cur") ;
winform.plusCur.onMouseDown = function(wParam,lParam){
    win.cur.beginCur();
    winform.plusCur.capture = true;
    winform.lastSpyHwnd = null;
}
    
winform.plusCur.onMouseUp = function(wParam,lParam){
    winform.plusCur.capture = false;
    win.cur.endCur();
    frmMask.show(false);
}

import key;  

var prevInspectX,prevInspectY,prevInspectTime;

var uiaInspect = function(){
     
    var x,y = mouse.getPos();
     
    var tick = ..time.tick();
    if(prevInspectTime && prevInspectX && prevInspectY /*&& winform.uiaInspectInfo[["element"]]*/){
        var x2,y2 = math.abs(x-prevInspectX),math.abs(y-prevInspectY) 
        if(!(x2||y2)) {
            if(winform.uiaInspectInfo) ShowInspectInfo(winform.uiaInspectInfo.element,x,y);
            return;
        }
        
        if((x2<5) && (y2<5)){
            if(tick - prevInspectTime < 1000 ){
                if(winform.uiaInspectInfo) ShowInspectInfo(winform.uiaInspectInfo.element,x,y);
                return;
            }
        }   
            
    }
    
    prevInspectX,prevInspectY = x,y;
    prevInspectTime = tick; 
    
    //var ele = FlaUI.Spy.FromPoint(x,y);
    var ele = winex.accObject.fromPoint(x,y); 
    if(!ele) {
        return ; 
    }
    
    var res ; 
    ele.enum(
        function(accChild,accParent){
            x1,y1,cx,cy = accChild.location();
            if(x1 <= x and x <= (x1 + cx) and y1 <= y and y <= (y1 + cy)){
                res = accChild;
            }
        },{}
    );  
    if(res){
        ele = res;          
    }
    
    winform.uiaInspectInfo = { 
        hwnd = ele.hwnd();
        //window =  ele.$window;
    } 
    
    ShowInspectInfo(ele,x,y);       
}


var hwndTarget;   
tmid = winform.setInterval(
    function(hwnd,msg,id,tick){
        if( win.cur.beginning ){ 
            uiaInspect();
        }
        elseif( winform.chkCtrl.checked ){ 
            if( ( win.cur.beginning ) ||(
                key.getStateX("CTRL") 
                && !key.getStateX("SHIFT") 
                && !key.getStateX("ALT") 
                && !mouse.state()
                && !mouse.rb.state()
                && !mouse.mb.state() ) ){ 
                    
                for(i='A'#;'Z'#;1){ 
                    if(key.getStateX(i)){
                        return;
                    }
                }
                
                for(i='0'#;'9'#;1){ 
                    if(key.getStateX(i)){
                        return;
                    }
                }
                
                uiaInspect();
            } 
        } 
        else {
            frmMask.show(false);
        } 
    },700
)   

import win.ui.tooltip; 
winform.tooltipCtr = win.ui.tooltip( winform );//在窗口上创建tooltip控件 
winform.tooltipCtr.add( 
    btnQuery = "测试 XPath"; 
    plusCur = "请按住此图标并拖动到目标窗口"; 
    editControlType = "UIA 控件类型(ControlType)"; 
    editControlName = "UIA 控件名称(Name)"; 
    editPath = "启动目标应用程序的执行文件路径与启动参数";   
    editPid = "这是窗口所在目标进程的10进制ID,进程是正在运行的程序的实例,也就是一个执行中的程序。每一个进程都有它自己的地址空间,在一个进程中可以包含若干个执行线程";
    editHwnd = "句柄是一个系统对象的唯一标识,在 aardio 中窗口句柄是一个数值(静态类型为 addr ),其他类型句柄一般用指针表示( 静态类型 pointer ),当然他们的本质都是数值。";
);

winform.btnCtrlParent.skin({
    color={
        active=0xFF00FF00;
        default=0xFF000080;
        disabled=0xFF6D6D6D;
        hover=0xFFFF0000
    }
})

winform.btnCtrlParent.oncommand = function(id,event){
    if(winform.uiaInspectInfo[["element"]]){
        if(winform.uiaInspectInfo.element==winform.uiaInspectInfo.window){
            return winform.msgboxErr("已经到达根节点!");
        }
        
        ShowInspectInfo(winform.uiaInspectInfo.element.parent());
    }
    else {
        winform.msgboxErr("请先拖动探针到目标窗口");
    } 
}

winform.btnQuery.skin({
    iconColor={
        active=0xFF00FF00;
        default=0xFF000080;
        disabled=0xFF6D6D6D;
        hover=0xFFFF0000
    }
})
winform.btnQuery.oncommand = function(id,event){
    if(!winform.uiaInspectInfo[["window"]]){
        return winform.msgboxErr("请先拖动探针到目标窗口");
    }
    
    var ele = winform.uiaInspectInfo.window.FindFirstByXPath(winform.editXPath.text);
    if(!ele){
        return winform.msgboxErr('没有找到控件,\n请尝试用 // 替换部分 XPath 路径,例如:\n\n' + (winform.uiaInspectInfo.shortXPath : `//Edit[@Name="输入"]`) );   
    }
    
    ShowInspectInfo(ele);
}

winform.editCode.enablePopMenu({
    {};
    { "全选 + 复制";  function(id){
        winform.editCode.selectAll();
        winform.editCode.copy()
    } };
    { "运行代码";  function(id){
        loadcodex(winform.editCode.text);
    } }; 
})

winform.btnHelp.oncommand = function(id,event){
    import process;
    process.openUrl("https://mp.weixin.qq.com/s/uEJSete63SQgJYEHw2PacQ")
}

winform.show(true);
win.setTopmost(winform.hwnd,true);

win.loopMessage();
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,454评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,553评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,921评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,648评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,770评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,950评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,090评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,817评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,275评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,592评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,724评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,409评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,052评论 3 316
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,815评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,043评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,503评论 2 361
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,627评论 2 350

推荐阅读更多精彩内容