2009-05-01 39 views
0

好吧,這是一個相當複雜的問題,但它看起來像autoit IE.au3項目已經完成了艱苦的工作。所以現在只需要有人熟練使用ruby和win32api,並且可能還需要自動學習如何將使用IE.au3編寫的函數轉換爲ruby。最終的結果是我想用嵌入式IE瀏覽器(IE嵌入在另一個應用程序中)使用Watir。我已經測試過,autoit函數對我正在使用的應用程序正常工作,但是我更喜歡使用watir(這是ruby)而不是autoit來測試html。使用ruby獲取嵌入式IE瀏覽器的COM對象win32api

我可以得到嵌入式瀏覽器的hwnd沒有問題(通過與autoit接口和使用自動化ControlGetHandle函數 - 注意到我無法與IE.au3接口,因爲它沒有內置到自動DLL,它的用戶定義函數庫 - UDF)。下面是我需要翻譯的功能(我還包括這個函數調用的另外兩個短函數,但我並不真的需要這些,我已經證實了我的翻譯過去)。

;=============================================================================== 
; 
; Function Name: __IEControlGetObjFromHWND() 
; Description:  Returns a COM Object Window reference to an embebedded Webbrowser control 
; Parameter(s):  $hWin  - HWND of a Internet Explorer_Server1 control obtained for example: 
;     $hwnd = ControlGetHandle("MyApp","","Internet Explorer_Server1") 
; Requirement(s): Windows XP, Windows 2003 or higher. 
;     Windows 2000; Windows 98; Windows ME; Windows NT may install the 
;     Microsoft Active Accessibility 2.0 Redistributable: 
;     http://www.microsoft.com/downloads/details.aspx?FamilyId=9B14F6E1-888A-4F1D-B1A1-DA08EE4077DF&displaylang=en 
; Return Value(s): On Success - Returns DOM Window object 
;     On Failure - 0 and sets @ERROR = 1 
; Author(s):  Larry with thanks to Valik 
; 
;=============================================================================== 

Func __IEControlGetObjFromHWND(ByRef $hWin) 
    DllCall("ole32.dll", "int", "CoInitialize", "ptr", 0) 
    Local Const $WM_HTML_GETOBJECT = __IERegisterWindowMessage("WM_HTML_GETOBJECT") 
    Local Const $SMTO_ABORTIFHUNG = 0x0002 
    Local $lResult, $typUUID, $aRet, $oIE 
MsgBox(0, "msg", $WM_HTML_GETOBJECT) 


    __IESendMessageTimeout($hWin, $WM_HTML_GETOBJECT, 0, 0, $SMTO_ABORTIFHUNG, 1000, $lResult) 

    $typUUID = DllStructCreate("int;short;short;byte[8]") 
    DllStructSetData($typUUID, 1, 0x626FC520) 
    DllStructSetData($typUUID, 2, 0xA41E) 
    DllStructSetData($typUUID, 3, 0x11CF) 
    DllStructSetData($typUUID, 4, 0xA7, 1) 
    DllStructSetData($typUUID, 4, 0x31, 2) 
    DllStructSetData($typUUID, 4, 0x0, 3) 
    DllStructSetData($typUUID, 4, 0xA0, 4) 
    DllStructSetData($typUUID, 4, 0xC9, 5) 
    DllStructSetData($typUUID, 4, 0x8, 6) 
    DllStructSetData($typUUID, 4, 0x26, 7) 
    DllStructSetData($typUUID, 4, 0x37, 8) 


    MsgBox(0, "lResult", $lResult) 


    $aRet = DllCall("oleacc.dll", "long", "ObjectFromLresult", "lresult", $lResult, "ptr", DllStructGetPtr($typUUID), _ 
      "wparam", 0, "idispatch*", 0) 
MsgBox(0, "aRet4", $aRet[4]) 
    If IsObj($aRet[4]) Then 
     $oIE = $aRet[4] .Script() 
     ; $oIE is now a valid IDispatch object 
     Return $oIE.Document.parentwindow 
    Else 
     SetError(1) 
     Return 0 
    EndIf 
EndFunc ;==>__IEControlGetObjFromHWND 
;=============================================================================== 
; Function Name: __IERegisterWindowMessage() 
; Description:  Required by __IEControlGetObjFromHWND() 
; Author(s):  Larry with thanks to Valik 
;=============================================================================== 
Func __IERegisterWindowMessage($sMsg) 
    Local $aRet = DllCall("user32.dll", "int", "RegisterWindowMessage", "str", $sMsg) 
    If @error Then Return SetError(@error, @extended, 0) 
    Return $aRet[0] 
EndFunc ;==>__IERegisterWindowMessage 

;=============================================================================== 
; Function Name: __IESendMessageTimeout() 
; Description:  Required by __IEControlGetObjFromHWND() 
; Author(s):  Larry with thanks to Valik 
;=============================================================================== 
Func __IESendMessageTimeout($hWnd, $msg, $wParam, $lParam, $nFlags, $nTimeout, ByRef $vOut, $r = 0, $t1 = "int", $t2 = "int") 
    Local $aRet 
    $aRet = DllCall("user32.dll", "long", "SendMessageTimeout", "hwnd", $hWnd, "int", $msg, $t1, $wParam, _ 
      $t2, $lParam, "int", $nFlags, "int", $nTimeout, "int*", "") 
    If @error Then 
     $vOut = 0 
     Return SetError(@error, @extended, 0) 
    EndIf 
    $vOut = $aRet[7]  
    If $r >= 0 And $r <= 4 Then Return $aRet[$r] 
    Return $aRet 
EndFunc ;==>__IESendMessageTimeout 

這裏是我到目前爲止(其中大部分來自於淨另一個海報誰是試圖解決同樣的問題來了,似乎是在正確的軌道上):

def get_control_from_hwnd(hnd) 
    Win32API.new("ole32", "CoInitialize", ['P'] , 'I').call(0) 

    reg_msg = Win32API.new("user32", "RegisterWindowMessage", ['P'] ,'I').call("WM_HTML_GETOBJECT") 
    puts "msg: " + reg_msg.to_s 
    result=" "*16 
    aInt = [0xA7, 0x31, 0x0, 0xA0, 0xC9, 0x8, 0x26, 0x37].pack 'I*' 
    a = [0x626FC520, 0xA41E, 0x11CF, aInt].pack 'IIIP' 

    sendMessagetimeout = Win32API.new("user32", "SendMessageTimeout", ['L','I','I','I','I','I','P'] , 'L') 
    sendMessagetimeout.call(hnd.hex, reg_msg, 0, 0, SMTO_ABORTIFHUNG, 1000, result) 

    puts "result unpacked: " + result.unpack("L").to_s #i can confirm this is the same as the lResult from the autoit functioin 

    idisp=0 
    #the problem is likely either here or the next line afterwards 
    oIE = Win32API.new("oleacc", "ObjectFromLresult", ['P','P','I','P'] , 'L') 


    oIE.call(result, a, 0, idisp) 
    puts "idisp: " + idisp.to_s 
    # returning zero 
    puts idisp.unpack("L") 

end 

好吧我知道這裏的工作比任何人都願意做得更多,但也許如果你看看我的翻譯和原文,有些東西可能會跳出來,因爲你錯了。我肯定會爲任何想出解決方案的人提供賞金

回答

0

不能相信我們正在做同樣的事情,雖然我試圖用Perl來做。我不知道Ruby,但看着腳本,它幾乎看起來像Perl。看看這個線程在autoIt,我仍然試圖解決問題http://www.autoitscript.com/forum/index.php?showtopic=104894。但我想我可能已經得到了這個idisp。兩個變化:

1)我打包結構的方式有點不同。我的$ iid如下所示: pack('LSSC8',0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37)。所以在Ruby中,我猜它會是[0x626FC520,0xA41E,0x11CF,0xA7,0x31,0x00,0xA0,0xC9,0x08,0x26,0x37] .pack'LSSC8'?我不知道正確的語法,但你明白了。 2)我解壓從SendMessageTimeout &的「結果」,然後將它傳遞給ObjectFromLresult。如果我直接通過結果,我會得到0。

但這就像我走了。