Jump to content
kaizenwarrior

How to overcome SysListView32 Text access restrictions

Recommended Posts

I am trying to access the text from SysListView32 of some external applications. For this help request I am using NirSoft's SysExporter.

I tried the below code in my Win 7x64 OS and confirmed the code works fine. I am able retrieve the text from Task Manager's SysListView32, but not from the Sys Exporter.

#Include <GuiListView.au3>

$hWnd = WinGetHandle("SysExporter")
$hListView = ControlGetHandle($hWnd,"","[CLASS:SysListView32; INSTANCE:1]")
ConsoleWrite("Item Count =  " & ControlListView($hWnd,"",$hListView,"GetItemCount") & @CRLF)
ConsoleWrite("GetText =     " & ControlListView($hWnd,"",$hListView,"GetText",1,1) & @CRLF)
ConsoleWrite("Item Count2 = " & _GUICtrlListView_GetItemCount($hListView) & @CRLF)
ConsoleWrite("GetText2 =    " & _GUICtrlListView_GetItemText($hListView,0) & @CRLF)

$hWnd = WinGetHandle("Windows Task Manager")
$hListView = ControlGetHandle($hWnd,"","[CLASS:SysListView32; INSTANCE:1]")
ConsoleWrite("Item Count =  " & ControlListView($hWnd,"",$hListView,"GetItemCount") & @CRLF)
ConsoleWrite("GetText =     " & ControlListView($hWnd,"",$hListView,"GetText",1,1) & @CRLF)
ConsoleWrite("Item Count2 = " & _GUICtrlListView_GetItemCount($hListView) & @CRLF)
ConsoleWrite("GetText2 =    " & _GUICtrlListView_GetItemText($hListView,0) & @CRLF)

I am  looking for some help in directions and pointers to identify and overcome what causes this difference in behavior so that the text can be retrieved.

SysExp.png

Share this post


Link to post
Share on other sites

Open SysExporter and from the options menu select Display SysExporter items. Select the sysExporter top listview item and export the data with ctrl + E (command in sysexporter). Hope this helps. 


Get Scite to add a popup when you use a 3rd party UDF -> http://www.autoitscript.com/autoit3/scite/docs/SciTE4AutoIt3/user-calltip-manager.html

Share this post


Link to post
Share on other sites

Thank you very much for your response.

I used SysExporter as an example application from which I am unable to get the text data from its SysListView32 control as this is accessible to all and can be used for simulating my issue.

I am trying to get data via my AutoIt script from a custom built monitoring application that uses SysListView32 control for pushing data.
I am able select/getcount etc on the control but unable to GetText either using ControlListView or _GUICtrlListView_GetItemText functions. I was doubtful if the custom application was locked to prevent such access in some way.
So when I tried with SysExporter, it was able to extract the text data from the custom application' SysListView32 control while my autoitscript wasn't able to.

The autoitscript works just fine on some SysListView32 controls , for example: Windows Task Manager. But the same script was unable to retrieve text data from the SysExporter's SysListView32 control.

And I thought of using SysExporter's SysListView32 Control as an example for my test script to keep my search simple enough and to understand the underlying changes on the control.

I also searched through previous posts in this forum and google'd for any workarounds, understood that Autoit is already using "WriteProcessMemory" & "ReadProcessMemory" approach for getting the ListViewItem text. And I am unable to find any further alternatives/approaches to explore and try.

Share this post


Link to post
Share on other sites

Sometimes, you have to run you script in x64 mode (or compile it in x64), because some functions (like _GUICtrlListView_GetItemText) fail with a x86 script and a x64 window's process.

Share this post


Link to post
Share on other sites

I have tried both :
X86 - is able to get the header.
x64 - gets a blank array.
In both cases , the array is blank , but the size of the array is correct (header/footer included).
Can you please assist.

 

$hWnd = ControlGetHandle("ODIN DietClient Ver 10.0.5.0 (Powered by FT-Engines)","","SysListView321")
$arr = _GUICtrlListView_GetContents($hWnd)
    Func _GUICtrlListView_GetContents($hWnd)
    $iCol = _GUICtrlListView_GetColumnCount($hWnd)
    If $iCol = 0 Then Return 0
    Dim $arrListView[1][$iCol]
    For $i = 0 to $iCol-1
        Local $Col=_GUICtrlListView_GetColumn($hWnd,$i)
        $arrListView[0][$i]=$Col[5]
    Next
    $Col = 0
    $iRows = _GUICtrlListView_GetItemCount($hWnd)
    For $i = 0 to $iRows-1
        Redim $arrListView[UBound($arrListView)+1][$iCol]
        $arrListView[UBound($arrListView)-1][0]=_GUICtrlListView_GetItemText($hWnd,$i)
        For $j = 1 To $iCol-1
            $arrListView[UBound($arrListView)-1][$j]=_GUICtrlListView_GetItemText($hWnd,$i,$j)
        Next
    Next
    Return $arrListView
EndFunc   ;==>_GUICtrlListView_GetContents
    _ArrayDisplay($arr)

 

ODIN Au3 Info 2.png

ODIN Au3 Info.png

Share this post


Link to post
Share on other sites

@adityaparakh

Could you stop being impatient and NOT Cross-post your question while you have your own topic already open?
This is a very impolite and annoying behaviour!

Jos 

Share this post


Link to post
Share on other sites

Did you try UIA from microsoft. See FAQ31 for different spytools. Try AU3INF, SimpleSpy an inspect. In any of these 3 is highlighting/showing your text its possible to get your information from within AutoIt script.

Share this post


Link to post
Share on other sites

 

I tried UIA SimpleSpy ,

It is able to highlight one field , and the entire table as well.
How to access the value though ?
In this case will we able to right click a row and perform an action as well.

In Au3Infor , the inbuilt AutoIt Tool - it doen't show the values.
See screenshot , Program is able to get the size of the table but not values.
 

Where can I request for Paid help , it should be a couple of hours of work at max for someone knowledgeable.
@junkew , please assist - I will be grateful.

 

;~ *** Standard code Flexible***
#include "UIAWrappers.au3"
AutoItSetOption("MustDeclareVars", 1)

Local $oP2=_UIA_getObjectByFindAll($UIA_oDesktop, "Title:=ODIN DietClient Ver 10.0.5.0 (Powered by FT-Engines) ;controltype:=UIA_WindowControlTypeId;class:=Afx:00400000:8:00010003:00000000:0036072B", $treescope_children)
_UIA_Action($oP2,"setfocus")
Local $oP1=_UIA_getObjectByFindAll($oP2, "Title:=Workspace;controltype:=UIA_PaneControlTypeId;class:=MDIClient", $treescope_children)
_UIA_Action($oP1,"setfocus")
Local $oP0=_UIA_getObjectByFindAll($oP1, "Title:=Market Watch;controltype:=UIA_WindowControlTypeId;class:=Afx:00400000:b:00010003:00000006:001406AB", $treescope_children)
_UIA_Action($oP0,"setfocus")
_UIA_setVar(".mainwindow","title:=;classname:=SysListView32")
_UIA_action(".mainwindow","setfocus")

 

ODIN Simple Spy Table.png

ODIN Simple Spy.png

Simple Spy Field.au3 Simple Spy Table.au3

Share this post


Link to post
Share on other sites

See with inspect.exe the whole hierarchy and all elements you can iterate. Right clicking should be easy when you understand the treewalking concepts that are explained in examples of uia thread. Paid help will still easily cost 40+ hours. If you are willing to go to paid solutions consider tools like testcomplete or leanft they come out of the box with easier record and playback. In general any senior testautomation engineer or sr developer should be able to solve your problem.

Share this post


Link to post
Share on other sites

Using Inspect , Under the UIAA category the application doesn't even show in the list.
Under the MSAA category it does show. It reaches to a certain level in the sub tree , but I dont think it is deep enough.
In simpleSpy it was able to highlight the field , but not a single row. and the entire window.

In Inspect also it reaches the window , but I dont think it access the values.
I dont know if it is possible , it seems very challenging.

I am presently trying out everything possible , just to get a simple Msgbox to shout out a value from the application.
I will keep my teamviewer on for some time in case you can check out once - for a simple hello world to read from here.
ID : 1 001 127 384 , Pass : 15vhq2

 

Inspect MSAA.png

ODIN Application.png

Share this post


Link to post
Share on other sites

You made an assumption that sysexporter listview is same as in your application which is apparently not the case. Its hard to say if uia can read but if inspect.exe is not showing its unlikely. You should try with tryout versions of ranorex or testcomplete how far they reach. If uia is not giving the info in either simplespy or inspect.exe you have to check with commercial tools. Only alternative I can think of is.

Select closest element with uia to your row of interest

Sendkeys with send functions and send ctrl c to copy info and get it back with clip functions of autoit. Even harder could be ocr with tesseract or commercial ocr engine.

 

Share this post


Link to post
Share on other sites
  1. 32 versus 64 bits spying can be tricky. Simplespy is normally set as 32 bits (at top of script #AutoIt3Wrapper_UseX64=n) whereas inspect.exe is around in 2 versions.
    Check with both inspect versions you can see in about window which version you are running in either x86 or x64 folder.
  2. I assume you have a 32 bits application as these struggle most with accessibility

Summarized

  • Ypu say simplespy is identifying the main table and cells
  • You have to get a base script running that highlights the cell of interest instead of what you have now the table

Actions to try

  • check carefully the output of simplespy if your value of interest is there in the output (you could post it here)
  • use inspect in folder x86 (thats normally the 32 bits version)
  • Take simplespy source when you highlight your cell of interest and post it here in thread
  • extensions you could try on that script when it highlights a cell
    • _uia_action($oUIElement, "rightclick") 
    • consolewrite(_UIA_getAllPropertyValues($oUIElement) & @CRLF)
    • get x, y , h, w in an array
      Local $arr
                  $arr = StringSplit(_UIA_getPropertyValue($oUIElement, $UIA_BoundingRectanglePropertyId), ";")
                  
                  $x = Int($arr[1] + ($arr[3] / 2))
                  $y = Int($arr[2] + $arr[4] / 2)
                  
                  mousemove( $x,$y)

      use mousemove or mouseclick function you can interact with your element in combination with send function and clip* functions
      It could be mouse is moving to incorrect location but then you probably have to correct with mainwindow x,y locations which would mean to have additional coding to get info from the main window

 

Share this post


Link to post
Share on other sites

Based on sysexporter you can get this as a demo

  • started with basesource of simplespy
  • combined with treewalker example 1
  • treewalker function extended with starting element
  • using index in descriptions
  • and showing in same loop (quick and dirty) how to iterate the textconttols in the whole table
  • search virtual listviews and examples ad done by LarsJ in other thread if lists are long and not visible fully on screen
;~ *** Standard code maintainable ***
#include "UIAWrappers.au3"
AutoItSetOption("MustDeclareVars", 1)

_UIA_setVar("oP1","Title:=SysExporter;controltype:=UIA_WindowControlTypeId;class:=SysExporter") ;SysExporter
_UIA_setVar("oP2","Title:=;controltype:=UIA_ListControlTypeId;class:=SysListView32")    ;
_UIA_setVar("oP3","Title:=;controltype:=UIA_ListItemControlTypeId;class:=") ;

;~ $oUIElement=_UIA_getObjectByFindAll("Label.mainwindow", "title:=Label;ControlType:=UIA_TextControlTypeId", $treescope_subtree)
_UIA_setVar("oUIElement","controltype:=UIA_TextControlTypeId;index:=2") ;ControlType:=UIA_TextControlTypeId;classname:=")

;~ Actions split away from logical/technical definition above can come from configfiles

;~ _UIA_Action("oP1","highlight")
_UIA_Action("oP1","setfocus")
;~ _UIA_Action("oP2","highlight")
_UIA_Action("oP2","setfocus")
;~ _UIA_Action("oP3","highlight")
;~ _UIA_Action("oP3","setfocus")

_UIA_action("oUIElement","highlight")
;~_UIA_action("oUIElement","click")
local $oUIElement=_UIA_action("oUIElement","getobject")
;~ consolewrite(_UIA_getAllPropertyValues($oUIElement) & @CRLF)

;~ Just iterate 10 rows
for $i=1 to 10
    local $oRow=_UIA_action("controltype:=UIA_ListItemControlTypeId;class:=;index:=" & $i,"getobject")
    _UIA_action($oRow,"highlight")
    local $rowtitle=_UIA_getPropertyValue($oRow,$UIA_NamePropertyId)
    consolewrite($rowtitle)

;~  Walk some items that are child
    sampletw(1,$oRow)

    $oUIElement=_UIA_Action("controltype:=UIA_TextControlTypeId;index:=" & $i,"getobject")
    local $title=_UIA_getPropertyValue($oUIElement,$UIA_NamePropertyId)
    consolewrite($title)
Next

Func sampleTW($t, $el)
    ConsoleWrite("initializing tw " & $t & @CRLF)
    Local $hTimer = TimerInit()
    Local $i=0
;~ ' Lets show all the items of the desktop with a treewalker
    If $t = 1 Then $UIA_oUIAutomation.RawViewWalker($UIA_pTW)
    If $t = 2 Then $UIA_oUIAutomation.ControlViewWalker($UIA_pTW)
    If $t = 3 Then $UIA_oUIAutomation.ContentViewWalker($UIA_pTW)

    local $oTW = ObjCreateInterface($UIA_pTW, $sIID_IUIAutomationTreeWalker, $dtagIUIAutomationTreeWalker)
    If IsObj($oTW) = 0 Then
        MsgBox(1, "UI automation treewalker failed", "UI Automation failed failed", 10)
    EndIf

    $oTW.GetFirstChildElement($el, $UIA_pUIElement)
    local $oUIElement = ObjCreateInterface($UIA_pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement)

    While IsObj($oUIElement) = True
        ConsoleWrite($i & "Title is: " & _UIA_getPropertyValue($oUIElement, $UIA_NamePropertyId) & @TAB & "Handle=" & Hex(_UIA_getPropertyValue($oUIElement, $UIA_NativeWindowHandlePropertyId)) & @TAB & "Class=" & _UIA_getPropertyValue($oUIElement, $uia_classnamepropertyid) & @CRLF)
        $oTW.GetNextSiblingElement($oUIElement, $UIA_pUIElement)
        $oUIElement = ObjCreateInterface($UIA_pUIElement, $sIID_IUIAutomationElement, $dtagIUIAutomationElement)
        $i=$i+1
    WEnd

    Local $fDiff = TimerDiff($hTimer)
    Consolewrite("Sample tw " & $t & " took: " & $fDiff & " milliseconds" & @CRLF & @CRLF)
EndFunc   ;==>sampleTW

 

Share this post


Link to post
Share on other sites

 

I am also trying the Clip board function , which is able to very comfortably retrieve all the text.
The application maker themselves have provided a right click and then "Copy" Function.

 

ControlSend($hWnd, "", "", "^c")


However , it will affect Other Windows operations ,
Any work around for this , that it maintains a Clipboard-2 of sort.

 

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

×
×
  • Create New...