Jump to content
Sign in to follow this  

Disabling a button in an Internet Explorer_Server instance using IUIAutomation

Recommended Posts

Hello everyone,

I support an application which has an Internet Explorer_Server instance in a pane of the application. There are a few buttons we would like to disable in the application, as it causes many an issue whenever users click on the buttons. The buttons which are part of the application/program are easy to disable (there was a "Print" button which we have disabled this way, thus forcing the user to use the "File->Print" option as that is the preferred method) but those which are part of the Internet Explorer_Server pane were inaccessible. Enter Junkew's IUIAutomation UDF.

I've been trying to follow the threads regarding IUIAutomation, and while I've been able to highlight the button (which in itself is a great accomplishment in my view) I can't find a way to disable said button. Is this even possible? If this were a regular button, I could get the handle of the control and manipulate it that way. I understand that the "automation" part doesn't include disabling items (who does that, right?) but I was wondering if someone savvier than myself knew of a method to do this.

Below is the code provided by simple spy (which I commented out to use the shorter version of the program at the end) Some information has been removed, but it was mostly to protect innocent servers. :-) Any guidance/assistance would be greatly appreciated.

#include "UIAWrappers.au3"
AutoItSetOption("MustDeclareVars", 1)

Local $oP13=_UIA_getObjectByFindAll($UIA_oDesktop, "Title:=[Horizon Ambulatory Care];controltype:=UIA_WindowControlTypeId;class:=WindowsForms10.Window.8.app4", $treescope_children)
Local $oP12=_UIA_getObjectByFindAll($oP13, "Title:=Workspace;controltype:=UIA_PaneControlTypeId;class:=WindowsForms10.MDICLIENT.app4", $treescope_children)
Local $oP11=_UIA_getObjectByFindAll($oP12, "Title:=Horizon Ambulatory Care;controltype:=UIA_WindowControlTypeId;class:=WindowsForms10.Window.8.app4", $treescope_children)
Local $oP10=_UIA_getObjectByFindAll($oP11, "Title:=;controltype:=UIA_PaneControlTypeId;class:=Shell Embedding", $treescope_children)
Local $oP9=_UIA_getObjectByFindAll($oP10, "Title:=;controltype:=UIA_PaneControlTypeId;class:=Shell DocObject View", $treescope_children)
Local $oP8=_UIA_getObjectByFindAll($oP9, "Title:=info.sys:12200/hac/clinical/frame/showMainFrame;controltype:=UIA_PaneControlTypeId;class:=Internet Explorer_Server", $treescope_children)
Local $oP7=_UIA_getObjectByFindAll($oP8, "Title:=HAC;controltype:=UIA_PaneControlTypeId;class:=", $treescope_children)
Local $oP6=_UIA_getObjectByFindAll($oP7, "Title:=info.sys:12200/hac/clinical/frame/showRootFrame;controltype:=UIA_CustomControlTypeId;class:=", $treescope_children)
Local $oP5=_UIA_getObjectByFindAll($oP6, "Title:=Root Frame Page;controltype:=UIA_PaneControlTypeId;class:=", $treescope_children)
Local $oP4=_UIA_getObjectByFindAll($oP5, "Title:=info.sys:12200/hac/clinical/workFlow/worklist/tabBarHandler/showFrameSet?activeTab=0;controltype:=UIA_CustomControlTypeId;class:=", $treescope_children)
Local $oP3=_UIA_getObjectByFindAll($oP4, "Title:=;controltype:=UIA_PaneControlTypeId;class:=", $treescope_children)
Local $oP2=_UIA_getObjectByFindAll($oP3, "Title:=info.sys:12200/hac/clinical/workFlow/worklist/showWorklist;controltype:=UIA_CustomControlTypeId;class:=", $treescope_children)
Local $oP1=_UIA_getObjectByFindAll($oP2, "Title:=Worklist;controltype:=UIA_PaneControlTypeId;class:=", $treescope_children)
Local $oP0=_UIA_getObjectByFindAll($oP1, "Title:=;controltype:=UIA_CustomControlTypeId;class:=", $treescope_children)
;~ First find the object in the parent before you can do something
;~$oUIElement=_UIA_getObjectByFindAll("Delete.mainwindow", "title:=Delete;ControlType:=UIA_ButtonControlTypeId", $treescope_subtree)
Local $oUIElement=_UIA_getObjectByFindAll($oP0, "title:=Delete;ControlType:=UIA_ButtonControlTypeId", $treescope_subtree)
ConsoleWrite("Value: " & _UIA_action($oUIElement,"right") & @CRLF)

_UIA_SetVAR("HACWindow","Title:=[Horizon Ambulatory Care];controltype:=UIA_WindowControlTypeId;class:=WindowsForms10.Window.8.app4")

ConsoleWrite("HAC? " & _UIA_Action("HACWindow","setfocus") & @CRLF)
ConsoleWrite("Pane? " & _UIA_Action("TaskListPane","setfocus") & @CRLF)
ConsoleWrite("Button? " & _UIA_Action("DeleteButton","highlight") & @CRLF)


Share this post

Link to post
Share on other sites

Some views, but no replies. I'm guessing it's not possible to do this. Still...

@junkew: Found an MSDN article about Registering Custom Properties, Events, and Control Patterns, but not sure how to implement this approach in AutoIt. I may not be understanding this correctly, but would this allow one to add a custom property to a button which UIAutomation is able to click/highlight/etc? In the snippet above, your libraries can highlight and click on the button. But I've found no way to disable it. So, could a custom property be added to disable any button seen by the Automation library?

Thank you all for your time!

Share this post

Link to post
Share on other sites

A custom property must be implemented by the provider of the application before it can be used by the client. A client cannot create a custom property. This method does not seem to be a solution.

If you can disable the button manually, you can probably automate the process too.

A button is usually supplied with an enabled property ($UIA_IsEnabledPropertyId). You can use the Spy tool or Inspect.exe to figure out, if you can set the value ($UIA_ValuePatternId) of this property.

Share this post

Link to post
Share on other sites


Thank you for the reply. Upon further examination of the output of simplespy, I see the following:

UIA_IsValuePatternAvailable:= <False>
UIA_IsWindowPatternAvailable:= <False>
UIA_ValueIsReadOnly:= <True>

Edited entry: could the Legacy IAccessiblePattern part be used for my purpose?

UIA_IsLegacyIAccessiblePatternAvailable:= <True>
UIA_LegacyIAccessibleChildId:= <0>
UIA_LegacyIAccessibleName:= <Delete>
UIA_LegacyIAccessibleRole:= <43>
UIA_LegacyIAccessibleState:= <1048576>
UIA_LegacyIAccessibleDefaultAction:= <Press>

Your help is greatly appreciated!

Edited by SanCon

Share this post

Link to post
Share on other sites

I don't think it looks too good. The role value = 43 = 0x2b = $ROLE_SYSTEM_PUSHBUTTON and the state value = 1048576 = 0x100000 = $STATE_SYSTEM_FOCUSABLE does not seem to be of any help. I'm afraid it's not possible to disable the button. At least not with usual automation code.

Maybe it's possible to catch a mouse click on the button with some kind of hook procedure and simply cancel the click event. You probably need a DLL file to do that. This excludes AutoIt. Another problem with such a solution is, that the user can't see that the mouse click is cancelled. The user will probably click a lot of times until he gives up. Unless you display a msgbox or something for the user.

Share this post

Link to post
Share on other sites

Thank you again, @LarsJ. With my limited understanding, I thought as much, but I know that some of the members in the AutoIt community are quite resourceful. I thought about monitoring mouse activity, but now that you mention that it may not be possible to do it within AutoIt, I may have to give up on this endeavor.

Thank you again for your help!

Share this post

Link to post
Share on other sites

A systemwide low level mouse hook (WH_MOUSE_LL) where you (more or less) hook into the mouse driver can be implemented in pure AutoIt code. You'll find examples if you search.

A less intrusive method (WH_GETMESSAGE, WH_MSGFILTER, WH_SYSMSGFILTER) where you only hook into the processes of the specific application cannot be implemented entirely in AutoIt code. In this example you can see which part of the code you can implement in AutoIt code and which part must be implemented in a DLL. It was this way I had in mind.

If such a hook procedure is implemented in pure AutoIt code, you can only hook into a GUI which is running in the same process (or thread) as the hook procedure.

Share this post

Link to post
Share on other sites

WMGetObject should be possible to get the native ie object. Then you can reach dom object and us ie.au3 stuff on the object retrieved. If your application has an adressbar you can manipulate thru javascript in addressbar



Share this post

Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

  • Create New...