Jump to content

GUICtrlTreeView UDF - 64bit script on x86 control


Recommended Posts

I have troubles with moving script to 64bit - functions "_GUICtrlTreeView_GetImageIndex()" and "_GUICtrlTreeView_GetText()" stop working without any errors

treeView control belong some x86 application - and x86 script work with it .

What i can do about it? Is it bug in UDF?

#AutoIt3Wrapper_UseX64=Y
#include <GuiTreeView.au3>

Func SubFunction_GetState($hWnd)
    Local $TVShandle, $TVSSelHandle, $TVSCount, $TVSParentHandle, $TVSS, $i, $TVSItemHandle, $TVSItemIcon
    AutoItSetOption("WinTitleMatchMode", 2)
    WinWaitActive($hWnd)
    $TVShandle = ControlGetHandle($hWnd, "", "[NAME:_treeView]")
    $TVSSelHandle = _GUICtrlTreeView_GetSelection($TVShandle)
    ConsoleWrite(@crlf&"$TVSSelHandle = "&$TVSSelHandle&@crlf&"@Error = "&@error&@crlf)

    $TVSCount = _GUICtrlTreeView_GetSiblingCount($TVShandle, $TVSSelHandle)
    ConsoleWrite(@crlf&"$TVSCount = "&$TVSCount&@crlf&"@Error = "&@error&@crlf)

    $TVSParentHandle = _GUICtrlTreeView_GetParentHandle($TVShandle)
    ConsoleWrite(@crlf&"$TVSParentHandle = "&$TVSParentHandle&@crlf&"@Error = "&@error&@crlf)

    Local $TVSS[1] = [0]
    For $i = 0 To $TVSCount-1
        $TVSItemHandle = _GUICtrlTreeView_GetItemByIndex($TVShandle, $TVSParentHandle, $i)
        ConsoleWrite(@crlf&"$TVSItemHandle = "&$TVSItemHandle&@crlf&"@Error = "&@error&@crlf)

        $TVSItemIcon = _GUICtrlTreeView_GetImageIndex($TVShandle, $TVSItemHandle)
        ConsoleWrite("$TVSItemIcon = "&$TVSItemIcon&@crlf&"@Error = "&@error&@crlf)
        ConsoleWrite("_GUICtrlTreeView_GetText = "&_GUICtrlTreeView_GetText($TVShandle, $TVSItemHandle)&@crlf&"@Error = "&@error&@crlf)

        If $TVSItemIcon = 7 Then
            ReDim $TVSS[UBound($TVSS)+1]
            $TVSS[0] += 1
            $TVSS[$TVSS[0]] = $TVSItemHandle
            ConsoleWrite("_GUICtrlTreeView_GetText = !!!"&@crlf)
        EndIf
    Next

EndFunc

x86 script output:

$TVSSelHandle = 0x066F3FD0
@Error = 0

$TVSCount = 40
@Error = 0

$TVSParentHandle = 0x003CBFB8
@Error = 0

$TVSItemHandle = 0x066F3930
@Error = 0
$TVSItemIcon = 5
@Error = 0
_GUICtrlTreeView_GetText = Item01
@Error = 0

x64 script output:

$TVSSelHandle = 0x00000000066F3FD0
@Error = 0

$TVSCount = 40
@Error = 0

$TVSParentHandle = 0x00000000003CBFB8
@Error = 0

$TVSItemHandle = 0x00000000066F3930
@Error = 0
$TVSItemIcon = 0
@Error = 0
_GUICtrlTreeView_GetText = 
@Error = 0

 

Link to comment
Share on other sites

tried to search bug tracker for something similar - found #1816 and #2694

If change in $tagLVITEM "ptr Text" to "uint Text" (i.e. make it 32bit) _GUICtrlListView_GetItemText solve the problem (but not solves the bug).

 but it didn't help...

Also bug #1479 seems relevant

 

Edited by Iczer
addition
Link to comment
Share on other sites

This is not a bug. You must use a 32 bit AutoIt script to automate a 32 bit application. And you must use a 64 bit AutoIt script to automate a 64 bit application.

If you look at _GUICtrlTreeView_GetText it uses a TVITEMEX structure. On 64 bit this is a 80 byte structure. On 32 bit this is a 60 byte structure.

If your AutoIt script is running 64 bit a 80 byte structure is created. The communication between your script and the application takes place when the _SendMessage command (succeeding "If $fUnicode Then") is executed. $pMemory is a pointer to the structure. But the application running 32 bit expects a 60 byte structure. This means that the _SendMessage command fails and returns False (0).

Perhaps one can say that it is a mistake not to check the return value of the _SendMessage command and set @error in case of an error.

Func _GUICtrlTreeView_GetText($hWnd, $hItem = 0)
  If Not IsHWnd($hItem) Then $hItem = _GUICtrlTreeView_GetItemHandle($hWnd, $hItem)
  If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

  If $hItem = 0x00000000 Then Return SetError(1, 1, "")

  Local $tTVITEM = DllStructCreate($tagTVITEMEX)
  Local $tText
  Local $fUnicode = _GUICtrlTreeView_GetUnicodeFormat($hWnd)
  If $fUnicode Then
    $tText = DllStructCreate("wchar Buffer[4096]"); create a text 'area' for receiving the text
  Else
    $tText = DllStructCreate("char Buffer[4096]"); create a text 'area' for receiving the text
  EndIf

  DllStructSetData($tTVITEM, "Mask", $TVIF_TEXT)
  DllStructSetData($tTVITEM, "hItem", $hItem)
  DllStructSetData($tTVITEM, "TextMax", 4096)

  If _WinAPI_InProcess($hWnd, $__ghTVLastWnd) Then
    DllStructSetData($tTVITEM, "Text", DllStructGetPtr($tText))
    _SendMessage($hWnd, $TVM_GETITEMW, 0, $tTVITEM, 0, "wparam", "struct*")
  Else
    Local $iItem = DllStructGetSize($tTVITEM)
    Local $tMemMap
    Local $pMemory = _MemInit($hWnd, $iItem + 4096, $tMemMap)
    Local $pText = $pMemory + $iItem
    DllStructSetData($tTVITEM, "Text", $pText)
    _MemWrite($tMemMap, $tTVITEM, $pMemory, $iItem)
    If $fUnicode Then
      _SendMessage($hWnd, $TVM_GETITEMW, 0, $pMemory, 0, "wparam", "ptr")
    Else
      _SendMessage($hWnd, $TVM_GETITEMA, 0, $pMemory, 0, "wparam", "ptr")
    EndIf
    _MemRead($tMemMap, $pText, $tText, 4096)
    _MemFree($tMemMap)
  EndIf

  Return DllStructGetData($tText, "Buffer")
EndFunc   ;==>_GUICtrlTreeView_GetText

 

Edited by LarsJ
Link to comment
Share on other sites

How will you do it? On x64 a pointer is 8 byte. On x86 it's 4 byte. How will you store an 8 byte pointer in a 4 byte structure field? This is not just a problem for pointers. This is also a problem for the following data types: hwnd, handle, int_ptr, long_ptr, lresult, lparam, uint_ptr, ulong_ptr, dword_ptr, wparam and struct. You have to add a lot of additional code to handle this. All the additional code will make your script run slow.

When you have implemented all that code, your script will not work if the target application is running 64 bit. The 64 bit application still expects a 80 byte structure.

Have you considered how many functions you need to change in that way? You have to change _GUICtrlTreeView_GetImageIndex, too. How many more functions in the GuiTreeView UDF do you have to change? How many more functions in the other GUI UDFs do you have to change? How many functions in the WinApi and other UDFs do you have to change?

Believe me. It's a bad idea. Instead of messing around with the code in the standard UDFs, it's a much better idea to make sure that your own scripts can run as both 32 and 64 bit programs. And they probably can this by default. If you need to automate a 32 bit target application, run the script as a 32 bit program. If the target application is running 64 bit, run the script as a 64 bit program.

Link to comment
Share on other sites

problem is - i need to automate a 32 bit target application, but my script in peak memory consumption hitting upper limit for x86 and crush - it seems (?) it about 1400...1500 Mb. I wanted to counter that and get some speed by moving to 64 bit. If i have to divide script to 32 and 64bit parts... can i instead call functions from autoit_x86.dll from 64bit script? :sweating:

Link to comment
Share on other sites

Why does your script use so much memory? There seems to be something wrong. Does the target application also use that much memory? To try to solve the problems by porting your script to 64 bit will just make things worse. You should focus on why your script uses so many resources.

Link to comment
Share on other sites

It's big input files and then fileread uses up to 6x times of filesize and then up to 8...10x times uses regexp, and in the end sqlite give finishing blow to script...

64bit do not have this limit. all i need is 2-3Gb of memory. any way i cannot reduce memory consumption of filesize and regexp...

i'm working on sqlite for now

Link to comment
Share on other sites

If you run this version of _GUICtrlTreeView_GetText on a 64 bit system, you can get the text of a treeview item in a 32 bit application.

Func _GUICtrlTreeView_GetText32($hWnd, $hItem = 0)
  If Not IsHWnd($hItem) Then $hItem = _GUICtrlTreeView_GetItemHandle($hWnd, $hItem)
  If Not IsHWnd($hWnd) Then $hWnd = GUICtrlGetHandle($hWnd)

  If $hItem = 0x00000000 Then Return SetError(1, 1, "")

  ; All 8 byte data types for a 64 bit system changed to 4 byte uint's for a 32 bit system
  Local $tagTVITEMEX32 = "struct; uint Mask;struct; uint hItem;uint State;uint StateMask;uint Text;int TextMax;int Image;int SelectedImage;int Children;uint Param; endstruct;" & _
  "int Integral;uint uStateEx;uint hwnd;int iExpandedImage;int iReserved; endstruct"

  Local $tTVITEM = DllStructCreate($tagTVITEMEX32)
  Local $tText
  Local $fUnicode = _GUICtrlTreeView_GetUnicodeFormat($hWnd)
  If $fUnicode Then
    $tText = DllStructCreate("wchar Buffer[4096]"); create a text 'area' for receiving the text
  Else
    $tText = DllStructCreate("char Buffer[4096]"); create a text 'area' for receiving the text
  EndIf

  DllStructSetData($tTVITEM, "Mask", $TVIF_TEXT)
  DllStructSetData($tTVITEM, "hItem", BitShift( $hItem, -32 )) ; 8 byte value --> 4 byte value
  DllStructSetData($tTVITEM, "TextMax", 4096)

  If _WinAPI_InProcess($hWnd, $__ghTVLastWnd) Then
    DllStructSetData($tTVITEM, "Text", DllStructGetPtr($tText))
    _SendMessage($hWnd, $TVM_GETITEMW, 0, $tTVITEM, 0, "wparam", "struct*")
  Else
    Local $iItem = DllStructGetSize($tTVITEM)
    Local $tMemMap
    Local $pMemory = _MemInit($hWnd, $iItem + 4096, $tMemMap)
    Local $pText = $pMemory + $iItem
    DllStructSetData($tTVITEM, "Text", BitShift( $pText, -32 )) ; 8 byte value --> 4 byte value
    _MemWrite($tMemMap, $tTVITEM, $pMemory, $iItem)
    If $fUnicode Then
      _SendMessage($hWnd, $TVM_GETITEMW, 0, BitShift( $pMemory, -32 ), 0, "wparam", "ptr") ; 8 byte value --> 4 byte value
    Else
      _SendMessage($hWnd, $TVM_GETITEMA, 0, $pMemory, 0, "wparam", "ptr")
    EndIf
    _MemRead($tMemMap, $pText, $tText, 4096)
    _MemFree($tMemMap)
  EndIf

  Return DllStructGetData($tText, "Buffer")
EndFunc

 

Link to comment
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
 Share

×
×
  • Create New...