2014-04-09 4 views
1

UIAutomation을 사용하여 Chrome 브라우저에 액세스/제어하려고합니다 (예 : 현재 URL을 얻기 위해 다른 사람이 사용했던 방식을 사용).UI 자동화 - ElementFromHandle이 요소를 찾지 못했습니다.

연습 문제로,이 질문을 복제하려고합니다. - Retrieve current URL from C# windows forms application - 델파이. TLB를 가져 왔습니다. 그러나 ElementFromHandle에 대한 호출은 요소를 찾지 않습니다.

ElementFromHandle 방법의 서명은 다음과 같습니다

procedure TForm3.Button1Click(Sender: TObject); 
var 
    UIAuto: IUIAutomation; 
    element: IUIAutomationElement; 
    value: WideString; 
    h: PInteger; 
begin 
    new(h); 
    h^ := $1094E; 
    SetForegroundWindow(h^); 
    ShowWindow(h^, SW_SHOW); 
    UIAuto := CoCUIAutomation.Create; 
    UIAuto.ElementFromHandle(h, element); 
    if Assigned(element) then 
    begin 
    element.Get_CurrentName(value); 
    showmessage('found -' + value); 
    end 
    else 
    showMessage('not found'); 
end; 

통화가 SetForegroundWindow하고이 ShowWindow은 초점을 필요로하는 경우에 단지가있다 (하지만 난 그 것을 의심 :

function ElementFromHandle(hwnd: Pointer; out element: IUIAutomationElement): HResult; stdcall; 

내 테스트는 단순히 차이를 만들고하지 않을 것이다). Spy ++가 내가 액세스하려고 시도하고있는 Chrome Tab의 값을 보여 주므로 Handel (1094E)이 "옳다"는 것을 확인할 수 있습니다. Chrome의 활성 탭은 항상 핸들을보고합니다.

내 구현이 정확합니까? 위에서 구현 한 것보다 UIAutomation을 사용하는 것이 더 많습니까? 나는 전에 그것을 탐험 해본 적이 없다. 내가 ElementFromPoint을 사용하고 난 내 탭 X, Y의 측면에 앉아 알고 곳의 (하드 코딩) 값을 전달하는 경우

감사

편집

나는 발견했다 -이 작업을 수행합니다. 예 :

UIAuto := CoCUIAutomation.Create; 
    p.x := 2916; 
    p.y := 129; 
    UIAuto.ElementFromPoint(p, element); 
    if Assigned(element) then 

의 OnClick 위의 이벤트에 배치하면 위의 코드는 요소 인스턴스 (보너스입니다) 나도 기대하고있어 하나를 반환한다. 어쩌면 내가 ElementFromHandle Hwnd에 대한 잘못된 값을 전달하는거야? ++ 내 MS 스파이를 발견 즉, 나는 크롬의 "정상"수준의 핸들을 사용하고 있습니다 :

enter image description here

이 스파이에서 (데스크탑) ++ 바로 아래에 앉아있다.

+0

새로 전화를 끊으십시오. h를 HWND 유형으로 선언하십시오. 그것은 정수가 아닙니다. 다음 단계는 오류를 확인하는 것입니다. 일단 그 일을 마치면 우리에게 무슨 일이 일어나는지 알려주십시오. –

+0

문제는 포인터가 첫 번째 매개 변수에 대해 HWnd가 아님을 의미합니다. – Jason

+0

문제가 있습니다. 내가 대답으로 써 보자. –

답변

1

실수로 창 핸들을 ElementFromHandle에 전달하는 중입니다. HWND을 전달해야합니다. 대신 HWND의 주소를 전달합니다.

기능은 정말해야합니다 : 아마도

if Succeeded(UIAuto.ElementFromHandle(window, element)) then 
    .... 

: 다음과 같은 함수를 호출

var 
    window: HWND; 
.... 
window := HWND($1094E); 

을 :

function ElementFromHandle(hwnd: HWND; 
    out element: IUIAutomationElement): HResult; stdcall; 

당신이 할 대신 New에 전화를 제거한다 가장 큰 근본적인 문제는 오류 검사가 전혀 없다는 것입니다. 이러한 API 호출이 예외를 발생시키지 않는다는 것을 인식하기 위해 사고 방식을 조정해야한다고 생각합니다. 그들은 반환 가치를 통해 실패를보고합니다. 모든 단일 API 호출에서 실패했는지 확인해야합니다.

일반적인 방법 중 하나는 OleCheck으로 전화가 걸려 실패 할 경우 HRESULT 값을 예외로 변환하는 것입니다. 예를 들면 다음과 같습니다.

var 
    UIAuto: IUIAutomation; 
    element: IUIAutomationElement; 
    value: WideString; 
    window: HWND; 
.... 
window := HWND($1094E); 
SetForegroundWindow(window); 
ShowWindow(window, SW_SHOW); 
UIAuto := CoCUIAutomation.Create; 
OleCheck(UIAuto.ElementFromHandle(window, element)); 
OleCheck(element.Get_CurrentName(value)); 
ShowMessage('found -' + value); 
+0

확실히 형식 라이브러리를 가져온 방법이었습니다. 포인터 대신 HWnd로 변경하면 해결됩니다. 건배 – Jason

+0

호기심에서 벗어나서'ElementFromHandle' 선언이 잘못되었음을 어떻게 알았습니까? – Wodzu

+0

@ Wodzu 그런 식으로 문서화되어 있습니다. 그러나 코드를 보았을 때 사용자가 HWND 변수의 주소를 전달하는 것이 이상하다고 생각합니다. 그것은 피 호출자가 호출자에게 창을 돌려 줄 때 의미가 있습니다. 그러나이 경우에는 IN 파라미터이므로 HWND가 가치있게 전달 될 것으로 기대합니다. –

관련 문제