mmseng Posted August 28, 2020 Share Posted August 28, 2020 Let me preface this with the fact that I am completely new to AutoIt, and I'm sure my methods here are very naive. I'm trying to automate the use of the GUI of Autodesk's uninstall tool executable (which has no commandline support). The GUI looks like this: I'm trying something very simple, running the exe, grabbing the window handle, focusing it, and sending "Down" and "Space" keystrokes to check all the boxes. I haven't worked out all the logic yet, so for now I'm just sending a static number of keystrokes, and haven't even gotten to clicking the "Uninstall" button. Here is my code so far: #RequireAdmin Run("C:\Program Files (x86)\Common Files\Autodesk Shared\Uninstall Tool\R1\UninstallTool.exe") Local $handle = WinWait("[CLASS:#32770]", "", 1) ControlFocus("Autodesk Uninstall Tool", "", "SysTreeView321") Check() Check() Check() Check() Check() Check() Check() Check() Check() Func Check() Delay() Send("{Down}") Send("{Space}") EndFunc Func Delay() Sleep(500) EndFunc It works... sort of. The boxes get checked, but the exe doesn't seem to realize that the boxes are checked. It doesn't check child boxes when parent boxes are checked (a behavior that happens when checking boxes manually with a mouse), and the "Uninstall" button stays grayed out (it normally becomes available to click once any box is checked). Again, I'm sure I'm butchering the way this is supposed to work, so any insight and direction are greatly appreciated. Thanks. Link to comment Share on other sites More sharing options...
Nine Posted August 28, 2020 Share Posted August 28, 2020 A SysTreeView is accessible thru GUI TreeView UDF, which will give you more control over the object. Sending keys like you do is probably the worst approach to create a robust script. If you doing it for yourself, well good luck. If you are doing it for you corporation, forget about it. Now I understand you need some help, but it is going very hard for us to suggest specific code since we dont have access to your application. “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
Musashi Posted August 28, 2020 Share Posted August 28, 2020 28 minutes ago, Nine said: ... it is going very hard for us to suggest specific code since we dont have access to your application. Yes, it is ! 1 hour ago, mmseng said: ... Autodesk's uninstall tool executable (which has no commandline support) You might want to take a look at the following links. Maybe they contain a solution that makes the automation of the uninstall tool superfluous. How-to-Uninstall-Autodesk-Products-Silently-Using-Batch-Scripts uninstall-multiple-autodesk-software "In the beginning the Universe was created. This has made a lot of people very angry and been widely regarded as a bad move." Link to comment Share on other sites More sharing options...
Zedna Posted August 29, 2020 Share Posted August 29, 2020 Try this: #Include <String.au3> #Include <GuiTreeView.au3> Run("C:\Program Files (x86)\Common Files\Autodesk Shared\Uninstall Tool\R1\UninstallTool.exe") Local $handle = WinWait("[CLASS:#32770]", "", 1) ControlFocus("Autodesk Uninstall Tool", "", "SysTreeView321") $hTree = ControlGetHandle("Autodesk Uninstall Tool", "", "SysTreeView321") $hItem = _GUICtrlTreeView_GetFirstItem($hTree) While $hItem <> 0 _GUICtrlTreeView_SetChecked($hTree, $hItem) $hItem = _GUICtrlTreeView_GetNextSibling($hTree, $hItem) WEnd Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
mmseng Posted August 29, 2020 Author Share Posted August 29, 2020 1 hour ago, Musashi said: You might want to take a look at the following links. Maybe they contain a solution that makes the automation of the uninstall tool superfluous. @Musashi Thanks, but trust me, I wouldn't be here at all if I hadn't exhausted those options. I've crawled their spiderweb of articles half a dozen times. Outside of this manual uninstall tool, Autodesk only supports uninstalling their apps through MECM (which we are already doing), but their officially supported methods do not clean up all the garbage their apps leave behind (and this actually breaks some of the apps we're NOT uninstalling). For that matter the uninstall tool doesn't clean up fully either, but it comes much closer. I'm certainly not asking anyone here to try this, but I will just say in my defense that the Autodesk uninstall tool comes with every version of every Autodesk application ever installed anywhere. It's not exactly a niche application, and the desire to automate it is not unique to me and my use case. @Nine I appreciate the lead. I didn't find (or understand) anything directly useful in the examples for _GUITreeViewEx, but it at least gave me somewhere to start. I've done a lot of playing around with various functions now, but am still banging my head. Problem #1: there appears to be no way to reference individual list items in a SysTreeView32 object. Similar to the issues discussed in this thread, AU3Info simply doesn't recognize any item more granular than the TreeView itself. I've tried both the x86 and x64 versions. So that apparently precludes me from using things like _GUICtrlListView_ClickItem and _GUICtrlListView_GetItemPosition, because they both rely on references to individual list items. Problem #2: I've tried several variations on the theme of ControlTreeView. As noted in the OP, these do not actually cause the app to register that a "check" or "click" is happening. Same problem with ControlClick. I've confirmed this is a default behavior of the app. If I simply open the app and manually use the keyboard down arrow and spacebar to check the boxes, the app will never recognize that anything has been checked until I physically click the mouse on a checkbox. What's worse, even once I do that, the other keyboard-checked checkboxes are still not recognized as being checked, because unchecking the mouse-checked checkbox will cause the "Uninstall" button to gray itself out again. So that bodes terribly. I'm amazed at how garbage this app is, and I've been in IT for 13 years so that's saying something. Edit: @Zedna Thanks for your suggestion. You posted as I was typing and I'll look into it. In the meantime... I'm still up for trying new things though, so I'll post what I currently have (which demonstrates some of the things I've tried). Again, any input or suggestions are appreciated. expandcollapse popup#RequireAdmin #include <GuiListView.au3> Run("C:\Program Files (x86)\Common Files\Autodesk Shared\Uninstall Tool\R1\UninstallTool.exe") Sleep(1000) $hWnd = WinGetHandle("Autodesk Uninstall Tool") ControlFocus($hWnd, "", "SysTreeView321") $hTreeView = ControlGetHandle($hWnd, "", "[CLASS:SysTreeView32; INSTANCE:1]") $count = ControlTreeView($hWnd, "", $hTreeView, "GetItemCount") ConsoleWrite("There are " & $count & " (parent) checkboxes." & @CRLF) ; Expando boxes are 11 pixels in $xExpando = 11 ; Parent checkboxes are 30 pixels in $xCheckbox = 30 ; First expando/checkbox is 11 pixels down $y = 11 ; Each line is very close to, if not exactly 17 pixels $spacing = 17 For $i = 0 To ($count - 1) Step 1 $num = "#" & $i ; Get this checkbox text $text = ControlTreeView($hWnd, "", $hTreeView, "GetText", $num) ConsoleWrite("Checkbox #" & $i & ": " & $text & @CRLF) ; Trying to directly check the box ; https://www.autoitscript.com/autoit3/docs/functions/ControlTreeView.htm ; For some reason this uninstall tool only seems to respond to actual mouse clicks... wow. ;ControlTreeView($hWnd, "", $hTreeView, "Check", $num) ; Can't seem to get item IDs of individual list/tree items from a SysTreeView32 ; https://www.autoitscript.com/forum/topic/177397-accessing-individual-elements-within-a-systreeview32-control/?tab=comments#comment-1272879 ; https://www.autoitscript.com/forum/topic/187587-clicking-syslistview32-check-box-problem/ ; https://www.autoitscript.com/autoit3/docs/libfunctions/_GUICtrlListView_ClickItem.htm ;_GUICtrlListView_ClickItem($hWnd, $i, "left", False, 1) ; I was hoping this would give me a controlID for an individual item, so I could use it with ; the below functions, but it just returns the 0-based index again ;ControlTreeView($hWnd, "", $hTreeView, "Select", $num) ;$ref = ControlTreeView($hWnd, "", $hTreeView, "GetSelected") ;ConsoleWrite("Checkbox #" & $i & ": " & $ref & @CRLF) ;$refIndex = ControlTreeView($hWnd, "", $hTreeView, "GetSelected", 1) ;ConsoleWrite("Checkbox #" & $i & ": " & $refIndex & @CRLF) ; Not even sure how this works, but probably also depends on individual item IDs ; https://www.autoitscript.com/forum/topic/133367-how-click-on-an-item-of-a-listview/ ; https://www.autoitscript.com/autoit3/docs/libfunctions/_GUICtrlListView_GetItemPosition.htm ;$pos = _GUICtrlListView_GetItemPosition($hTreeView, 0) ;ConsoleWrite("Checkbox #" & $i & ": " & $pos[0] & "," & $pos[1] & @CRLF) ; This uses coords that are relative to the to the global screen (i.e. not helpful) ; https://www.autoitscript.com/autoit3/docs/functions/MouseClick.htm ;MouseClick("primary", 30, 11, 1) ; This uses coords that are relative to the TreeView item ; https://www.autoitscript.com/autoit3/docs/functions/ControlClick.htm ; Still doesn't trigger the app to respond properly ControlClick($hWnd, "", $hTreeView, "primary", 1, $xExpando, $y) Delay() ControlClick($hWnd, "", $hTreeView, "primary", 1, $xCheckbox, $y) $y = $y + $spacing ; Things to try/look into ; Manpulating checkbox state images? ; https://www.autoitscript.com/forum/topic/198343-solved-controlling-a-syslistview32-instance/?tab=comments#comment-1422916 ; https://www.autoitscript.com/forum/topic/86470-checking-the-state-of-a-check-box/ ; https://www.autoitscript.com/forum/topic/179394-checkboxes-overlay-icons-and-state-images-in-listviews/ ; https://www.autoitscript.com/forum/topic/158996-get-text-from-systreeview32/ ; https://www.autoitscript.com/wiki/ControlCommand ; https://www.autoitscript.com/forum/topic/166594-guitreeviewex-new-release-11-jan-15/ Delay() Next Func Delay() Sleep(250) EndFunc Thanks and regards. Link to comment Share on other sites More sharing options...
mmseng Posted August 29, 2020 Author Share Posted August 29, 2020 @Zedna Your code does work, but it unfortunately has the same problem as several of my other attempts, where the checkboxes are visually checked, but not recognized as being checked by the application. However your code also let me finally wrap my head around the differences between handles for the window vs. treeview vs. specific item, and also made me realize that I've been mix/matching _GUICtrlListView and _GUICtrlTreeView calls. So some of my testing has been invalid. While your _GUICtrlTreeView_SetChecked call still isn't working for this particular app, I've had some success using _GUICtrlTreeView_ClickItem. _GUICtrlTreeView_ClickItem unfortunately only clicks on the very left edge of the text of each row, which does nothing but select the text. However, from there I can grab the mouse position and do some dirty pixel math to move/click just far enough left check the checkbox. This action is actually recognized by the app, and checks each parent checkbox's child boxes and un-grays the "Uninstall" button, as expected. I'm wondering if there's a better way though. My working code is below. Unfortunately I'm guessing that using the mouse like this probably limits the portability of this solution (even more than it already is by virtue of needing to interact with the GUI), due to potential differences in endpoint screen resolutions. But it's a step in the right direction. It's just a shame that the app only properly recognizes mouse clicks. expandcollapse popup#RequireAdmin #Include <GuiTreeView.au3> ; Run app Run("C:\Program Files (x86)\Common Files\Autodesk Shared\Uninstall Tool\R1\UninstallTool.exe") ; Get handles for window and treeview Sleep(1000) $hWnd = WinGetHandle("Autodesk Uninstall Tool") $hTree = ControlGetHandle($hWnd, "", "SysTreeView321") ;$hTree = ControlGetHandle($hWnd, "", "[CLASS:SysTreeView32; INSTANCE:1]") ; Make sure window is focused ControlFocus($hWnd, "", $hTree) ;$count = ControlTreeView($hWnd, "", $hTree, "GetItemCount") ;ConsoleWrite("There are " & $count & " (parent) checkboxes." & @CRLF) ; Thanks to Zedna ; Get first item $hItem = _GUICtrlTreeView_GetFirstItem($hTree) While $hItem <> 0 ;ConsoleWrite("Item: " & $hItem & @CRLF) ; This unfortunately is still not properly recognized by the app ;_GUICtrlTreeView_SetChecked($hTree, $hItem) ; Click on this item instead _GUICtrlTreeView_ClickItem($hTree, $hItem, "primary", True, 1) ; Grab mouse position $itemX = MouseGetPos(0) $itemY = MouseGetPos(1) ;ConsoleWrite($itemX & "," & $itemY & @CRLF) ; Adjust mouse position $checkX = $itemX - 27 $checkY = $itemY + 8 ; Click at adjusted position Delay() MouseClick("primary", $checkX, $checkY, 1, 0) ; Move to next item $hItem = _GUICtrlTreeView_GetNextSibling($hTree, $hItem) Delay() WEnd ; TODO: Click on "Uninstall" button Func Delay() ;Sleep(250) EndFunc To be continued... Link to comment Share on other sites More sharing options...
Zedna Posted August 29, 2020 Share Posted August 29, 2020 Look here Resources UDF ResourcesEx UDF AutoIt Forum Search Link to comment Share on other sites More sharing options...
Nine Posted August 29, 2020 Share Posted August 29, 2020 (edited) here an idea, replace with : $hItem = _GUICtrlTreeView_GetFirstItem($hTree) Local $aPos While $hItem <> 0 ; get the display rectangle of the item $aPos = _GUICtrlTreeView_DisplayRect($hTree, $hItem, False) ; you may want to try True also, to see if that is helping _ArrayDisplay ($aPos) ; based on the array calculate more precisely the coordinates $hItem = _GUICtrlTreeView_GetNextSibling($hTree, $hItem) Sleep (250) WEnd or maybe this : $hItem = _GUICtrlTreeView_GetFirstItem($hTree) Local $aPos While $hItem <> 0 ; get the display rectangle of the item _GUICtrlTreeView_SelectItem ($hTree, $hItem, $TVGN_CARET) ControlSend ($hWnd, "", $hTree, "{SPACE}") $hItem = _GUICtrlTreeView_GetNextSibling($hTree, $hItem) Sleep (250) WEnd Have tried ControlTreeView with "check", "item" ? Edited August 29, 2020 by Nine “They did not know it was impossible, so they did it” ― Mark Twain Spoiler Block all input without UAC Save/Retrieve Images to/from Text Monitor Management (VCP commands) Tool to search in text (au3) files Date Range Picker Virtual Desktop Manager Sudoku Game 2020 Overlapped Named Pipe IPC HotString 2.0 - Hot keys with string x64 Bitwise Operations Multi-keyboards HotKeySet Recursive Array Display Fast and simple WCD IPC Multiple Folders Selector Printer Manager GIF Animation (cached) Screen Scraping Multi-Threading Made Easy Link to comment Share on other sites More sharing options...
mmseng Posted August 29, 2020 Author Share Posted August 29, 2020 Thank you both for the additional suggestions. I'll give them a try. Yes, I have tried this: ControlTreeView($hWnd, "", $hTreeView, "Check", $num) (it was one of the first things I tried which only visually checked the boxes) However I might want to try it again in combination with _GUICtrlTreeView_SelectItem, similar to your second suggestion. Perhaps checking the boxes might work properly if they are selected first. Cheers. Link to comment Share on other sites More sharing options...
mmseng Posted August 29, 2020 Author Share Posted August 29, 2020 (edited) I haven't looked into @Zedna's link yet, but I've ruled out @Nine's suggestions (for now). Firstly, _GUICtrlTreeView_SelectItem did not help anything. Following it with ControlSend($hWnd, "", $hTree, "{SPACE}"), or ControlTreeView($hWnd, "", $hTree, "Check", $num), or _GUICtrlTreeView_SetChecked($hTree, $hItem) all had the same result, where the checkboxes were only checked visually. So that's a bummer. Also, unfortunately it seems _GUICtrlTreeView_DisplayRect only returns the position of items RELATIVE to the item's parent tree, so this is no more accurate than using _GUICtrlTreeView_ClickItem + MouseGetPos + some dirty math + MouseClick. The only way I can see this methodology could be more accurate is if there were some way to return the ABSOLUTE coordinates of the actual checkbox. Otherwise, I'm always going to be guessing at how many pixels big the checkbox is and doing dirty math to find the rough center of it to click. The closer I can get absolute coordinates before making that guess, the more accurate this will be, and currently the closest I can get is with _GUICtrlTreeView_ClickItem + MouseGetPos. Next I'll look into the Winspector/WM_COMMAND stuff. Thanks again for the suggestions. Edited August 29, 2020 by mmseng Link to comment Share on other sites More sharing options...
Recommended Posts
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 accountSign in
Already have an account? Sign in here.
Sign In Now