jarmo / RAutomation

RAutomation
MIT License
100 stars 33 forks source link

Open menu method runtime error #100

Closed plastictreeofdoom closed 9 years ago

plastictreeofdoom commented 9 years ago

When using the "open" method from the ms_uia menu class, I have only received runtime errors. Example code is below, error seems to be consistent regardless of which application is being tested:

require 'rautomation'

window = RAutomation::Window.new( :title =>/Notepad++/, :adapter => 'ms_uia')
window.activate
view = window.menu(:name => 'View')
view.open

Output is as follows:

C:\Ruby22\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) C:/POC/error_example.rb
 (RuntimeError)
   at System.Windows.Automation.AutomationElement.GetCurrentPattern(AutomationPattern pattern)
   at MenuItemSelector.SelectMenuPath(HWND__* windowHandle, list<char const \*\,std::allocator<char const \*> >* menuItems)
   at MenuSelectPath(HWND__* windowHandle, SByte* errorInfo, Int32 errorInfoSize, list<char const \*\,std::allocator<char const \*> >* menuItems)
    from C:/POC/error_example.rb:6:in `<top (required)>'
    from -e:1:in `load'
    from -e:1:in `<main>'

Process finished with exit code 1

Thanks

leviwilson commented 9 years ago

I believe you're getting this error because the View menu item in Notepad++ is not an invokable item; the #open method is only for something that supports the InvokePattern in UIA.

For example, if you wanted to toggle "Word wrap" you would do this:

window = RAutomation::Window.new(title: /Notepad\+\+/, adapter: :ms_uia)
window.menu(text: 'View').menu(text: 'Word wrap').open
plastictreeofdoom commented 9 years ago

Thanks, the method is working for that (although unfortunately not for the applications I'm trying to test).

leviwilson commented 9 years ago

Have you tried manually doing it through UISpy to see if you can?

The trick to menus is that when they're nested like that, often the descendants are not populated until the parent is expanded.

Is your app a WinForm or WPF app?

On Apr 13, 2015 12:40 AM, "plastictreeofdoom" notifications@github.com wrote:

Thanks, the method is working for that (although unfortunately not for the applications I'm trying to test).

— Reply to this email directly or view it on GitHub.

plastictreeofdoom commented 9 years ago

WPF. Several elements happened to have the IsInvokePatternAvailable property value set to "True", and I was able to trigger those elements using both inspect.exe and the ms_uia adapter in RAutomation (but not when set to "False", as discussed above).

Unless there is a way to ignore that property, I'll request that the value be changed where possible.

Thanks.

leviwilson commented 9 years ago

From a purely UIA standpoing, if the inspection tools is saying that the InvokePattern is not available then using this method will not work.

Alternatively what you could do is perhaps do a #send_keys approach and try to invoke the menu item with a key combination? Probably something like this in the above example:

window.send_keys [:alt, 'vw', :enter]

Or something to that effect.

plastictreeofdoom commented 9 years ago

Are there any of the other methods (eg. click, when it's a control, button, etc.) that aren't dependentant on the InvokePattern value?

Keystrokes will work in some situations but not others.

Thanks.

leviwilson commented 9 years ago

The only other option I have for you is another gem that works at more of a lower-level with UIA than the current :ms_uia adapter in RAutomation does. At some point I will be swapping out the :ms_uia adapter to actually use this gem but have not had the time to do so.

The gem is called uia and can be found here.

plastictreeofdoom commented 9 years ago

Thanks Levi, I know there is a way to access those elements, as I've been able to use pywinauto, but would prefer to use RAutomation if possible.

I'll check out UIA and see if it makes a difference.

leviwilson commented 9 years ago

It absolutely makes a difference; trust me, I wrote both the adapter and the uia gem :wink:

The current :ms_uia adapter is more of a high-level wrapper for RAutomation; it doesn't expose a lot of the lower-level UIA stuff that you need currently.

What you'll likely need from uia is this. But rather than just grabbing the name property like that example is, you would likely want to either #click or #click_center on it. The difference is #click tries to find a "clickable point" from UIA, which isn't always available. #click_center tries to determine the point to click based on the bounding rectangle.

plastictreeofdoom commented 9 years ago

Thanks Levi, it appears to be working using uia.