【问题标题】:How to get COM object for embedded IE browser?如何获取嵌入式 IE 浏览器的 COM 对象?
【发布时间】:2010-10-23 04:50:58
【问题描述】:

如何将此函数从 AutoIt 的 IE.au3 UDF 转换为 Ruby?意图是将 Watir 与 Internet Explorer 浏览器(嵌入在另一个应用程序中)一起使用。

AutoIt 功能运行良好,但我更喜欢 Watir(它是 Ruby)。我可以使用 ControlGetHandle() 获取嵌入式浏览器的句柄,这在 AutoIt dll 中不可用。

下面是翻译功能(还有另外两个我不需要的)。

;===============================================================================
;
; 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

【问题讨论】:

    标签: ruby internet-explorer winapi watir win32ole


    【解决方案1】:

    不敢相信我们正在做同样的事情,尽管我正在尝试在 Perl 中这样做。我不知道 Ruby,但看看脚本,它几乎看起来与 Perl 相似。看看 autoIt 上的这个线程,我仍在尝试解决问题http://www.autoitscript.com/forum/index.php?showtopic=104894。但我想我可能已经得到了 idisp。两个变化:

    1) 我打包结构的方式有点不同。我的 $iid 看起来像这样: 包('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。

    但我已经走了这么远。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-15
      • 2010-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-22
      • 2023-04-03
      • 1970-01-01
      相关资源
      最近更新 更多