需要应用程序架构的一些背景知识:
Windows 2003 / Apache-v2.2 / IE7 / Watir-v1.6.2 / Ruby-v1.8.5
为了点击IE中的链接/按钮,Watir提供同步“点击”方法和异步“click_no_wait”方法。 'click_no_wait'产生一个全新的ruby进程,连接回IE7窗口,点击链接/按钮。
这对我来说是失败的。由于click_no_wait正在产生一个新进程。它似乎无法看到IE7窗口连接到它并单击链接/按钮。 我必须使用'click_no_wait',因为IE弹出某个页面的对话框,以便另一个ruby线程可以关闭它。
我尝试了一些事情: - 使用fire_event('OnClick')而不是click_no_wait挂起像'click'那样的脚本。 - 通过注释'@ container.wait'修改'click',但'click!'本身就是挂起等待对话框关闭的API。 - 让'click_no_wait'产生一个新线程而不是一个进程',但是其他线程似乎在'click!'时被挂起了。调用在该线程中执行。这很奇怪。 - 使用与生成IE7进程完全相同的代码执行'click_no_wait'进程,但仍无法找到任何IE7窗口。
通过上面描述的'default'桌面,生成IE的代码基本上会执行一系列C ++调用,将IE7窗口附加到'winsta0'桌面:
- LogonUser() // log in as tester account
- OpenWindowStation("winsta0") // to get default desktop
- SetProcessWindowStation()
- // add the user to interactive window station using (GetUserObjectSecurity, GetSecurityDescriptorDacl, GetAclInformation, AddAce, SetSecurityDescriptorDacl, SetUserObjectSecurity)
- // add user to "default" desktop using APIs listed above.
- CreateEnvironmentBlock
- ImpersonateLoggedOnUser
- CreateProcessAsUser('iexplore.exe')
- // cleanup
在特定用户IE7下运行以下Watir脚本正在yield:
下运行$IE = Watir::IE.attach(:title, /Google/)
$IE.button(:name, 'btnG').click!
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:在`method_missing'中:Windows(WIN32OLERuntimeError) OLE错误代码:80040154 in HRESULT错误代码:0x80020009 发生了异常。来自c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246:in“each”
其中包含:
c:/ruby/lib/ruby/gems/1.8/gems/watir-1.6.2/lib/watir/ie-class.rb:246
shell = WIN32OLE.new("Shell.Application")
windows = shell.Windows ## Fails here
如果我能提供更多细节或消除歧义,请告诉我们! :)
谢谢, 沙恩。
答案 0 :(得分:0)
好的,我已经解决了自己的问题。
事实证明,Watir用于枚举IE窗口的方法(即Shell.Application)在用户空间中不起作用。因此,我必须编写一个中间应用程序来检索IE窗口的IWebBrowser2 COM指针,并修改'eval_in_spawned_process'Watir函数以将此句柄用于'pc = Watir :: IE.bind(iWebBrowserPtr)'。
我可能不需要外部应用程序来检索IWebBrowser2对象,但我不知道如何在Ruby中执行此操作,并且我已经拥有了一个可以用于此目的的IE BHO应用程序。< / p>
现在工作正常。 :)
的Watir /页-container.rb:56
# This evaluates a cmd (e.g. "button(:id, 1).click!") in a new ruby process
# This is to primarily avoid a script hanging while a modal dialog is displayed in IE.
# It gets an IE handle from our IE BHO based off of window handle. It needs to do this
# to get around the problem of finding the IE window itself using Shell.Application
# which does not work across User-contexts.
# Note: This change probably invalidates the Watir unit-test for this API.
def eval_in_spawned_process(command)
command.strip!
load_path_code = _code_that_copies_readonly_array($LOAD_PATH, '$LOAD_PATH')
ruby_code = "require 'watir/ie'; "
ruby_code << 'controller = WIN32OLE.new("HttpPlugin.Controller"); '
ruby_code << "window = controller.BrowserFromHWND(#{hwnd}); "
ruby_code << "pc = Watir::IE.bind(window); "
ruby_code << "pc.#{command}; "
exec_string = "start rubyw -e #{(load_path_code + '; ' + ruby_code).inspect}"
result = system(exec_string)
end