|
-
Jul 6th, 2002, 05:24 PM
#1
Thread Starter
New Member
Get text from ListView in another app
I think that it works different with a ListView than it does a ListBox for some reason. When Program A tries to get the text from a ListView in Program B, Program B crashes. Someone explained to me that Program A is trying to write to the memory of Program be or vice versa (something like that anyway), which apparently is a big no no.
The code I'm using is as follows:
Code:
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" ( _
ByVal hWnd1 As Long, _
ByVal hWnd2 As Long, _
ByVal lpsz1 As String, _
ByVal lpsz2 As String) As Long
Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
lParam As Any) As Long
Private Type LVITEM
mask As Long
iItem As Long
iSubItem As Long
state As Long
stateMask As Long
pszText As String
cchTextMax As Long
iImage As Long
lParam As Long
End Type
Private Const BM_CLICK = &HF5&
Private Const WM_SETTEXT = &HC
Private Const LVM_FIRST = &H1000
Private Const LVM_GETITEMCOUNT = (LVM_FIRST + 4)
Private Const LVM_GETITEM = (LVM_FIRST + 5)
Private Const LVM_GETSTRINGWIDTH = (LVM_FIRST + 17)
Private Const LVM_GETCOLUMN = (LVM_FIRST + 25)
Private Const LVM_GETITEMTEXT = (LVM_FIRST + 45)
Dim Lv As LVITEM
Dim MyText As String
Dim MySize As Long
Private Sub Command1_Click()
test123 = FindWindowEx(0, 0, vbNullString, "Test123")
frame1 = FindWindowEx(test123, 0, "ThunderFrame", vbNullString)
frame2 = FindWindowEx(frame1, 0, "ThunderFrame", vbNullString)
button = FindWindowEx(frame2, 0, "ThunderCommandButton", vbNullString)
LView = FindWindowEx(frame2, 0, "ListView20WndClass", vbNullString)
NumBuddies = SendMessage(LView, LVM_GETITEMCOUNT, 0, 0)
'Lv.mask = LVIF_TEXT
'Lv.iItem = 1
Lv.cchTextMax = Len(MyText)
Lv.pszText = MyText
MySize = SendMessage(LView, LVM_GETITEMTEXT, ByVal 1, ByVal Lv)
Text1.Text = test123
Text2.Text = frame1
Text3.Text = frame2
Text4.Text = button
Text5.Text = LView
Text6.Text = NumBuddies
Text7.Text = MySize
Text8.Text = MyText
End Sub
I don't quite understand the LVITEM thing, so maybe that's where I'm going wrong.
I've again uploaded the example programs to show what I am trying to achieve. You'll see that when Program A tries to get the text from a ListView in Program B, Program B crashes
I've read here that it is not possible to do it this way, but instead you have to use some other way whuch I is competly beyond me. Surely it should be possible and not too much omplicated as getting text from a ListBox¿
It may not be as complicated as it seems and might be me just missing something simple, but I'm new to all this so I'm not sure where I'm going wrong
Any help would be much appreciated.
Thanks
-
Jul 6th, 2002, 09:10 PM
#2
Member
the reason your program does not work is because the LVItem structure is not created within the same memort space as the program into which you are sending it in. when dealing with Listviews, Treeviews, etc you must create the structure within the other processes virtual memory space and then send it in.
use this function i wrote up to accomplish the task.
Code:
Public Const PROCESS_QUERY_INFORMATION = 1024
Public Const PROCESS_VM_OPERATION = &H8
Public Const PROCESS_VM_READ = &H10
Public Const PROCESS_VM_WRITE = &H20
Public Const STANDARD_RIGHTS_REQUIRED = &HF0000
Public Const MAX_LVMSTRING As Long = 255
Public Const MEM_COMMIT = &H1000
Public Const PAGE_READWRITE = &H4
Public Const LVIF_TEXT As Long = &H1
Public Type LV_ITEMA
mask As Long
iItem As Long
iSubItem As Long
state As Long
stateMask As Long
pszText As Long
cchTextMax As Long
iImage As Long
lParam As Long
iIndent As Long
End Type
Public Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcId As Long) As Long
Public Declare Function VirtualAllocEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal flAllocationType As Long, ByVal flProtect As Long) As Long
Public Declare Function VirtualFreeEx Lib "kernel32" (ByVal hProcess As Long, ByVal lpAddress As Long, ByVal dwSize As Long, ByVal dwFreeType As Long) As Long
Public Declare Function WriteProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByRef lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function ReadProcessMemory Lib "kernel32" (ByVal hProcess As Long, ByVal lpBaseAddress As Any, ByRef lpBuffer As Any, ByVal nSize As Long, lpNumberOfBytesWritten As Long) As Long
Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByRef lParam As Any) As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Function GetListviewItem(ByVal hWindow As Long, ByVal ProcessID As Long, ByVal pColumn As Long, ByVal pRow As Long) As String
Dim result As Long
Dim myItem As LV_ITEMA
Dim pHandle As Long
Dim pStrBufferMemory As Long
Dim pMyItemMemory As Long
Dim strBuffer() As Byte
Dim index As Long
Dim tmpString As String
Dim strLength As Long
'**********************
'init the string buffer
'**********************
ReDim strBuffer(MAX_LVMSTRING)
'***********************************************************
'open a handle to the process and allocate the string buffer
'***********************************************************
pHandle = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, False, ProcessID)
pStrBufferMemory = VirtualAllocEx(pHandle, 0, MAX_LVMSTRING, MEM_COMMIT, PAGE_READWRITE)
'************************************************************************************
'initialize the local LV_ITEM structure
'The myItem.iSubItem member is set to the index of the column that is being retrieved
'************************************************************************************
myItem.mask = LVIF_TEXT
myItem.iSubItem = pColumn
myItem.pszText = pStrBufferMemory
myItem.cchTextMax = MAX_LVMSTRING
'**********************************************************
'write the structure into the remote process's memory space
'**********************************************************
pMyItemMemory = VirtualAllocEx(pHandle, 0, Len(myItem), MEM_COMMIT, PAGE_READWRITE)
result = WriteProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
'*************************************************************
'send the get the item message and write back the memory space
'*************************************************************
result = SendMessage(hWindow, LVM_GETITEMTEXT, pRow, ByVal pMyItemMemory)
result = ReadProcessMemory(pHandle, pStrBufferMemory, strBuffer(0), MAX_LVMSTRING, 0)
result = ReadProcessMemory(pHandle, pMyItemMemory, myItem, Len(myItem), 0)
'**************************************************
'turn the byte array into a string and send it back
'**************************************************
For index = LBound(strBuffer) To UBound(strBuffer)
If Chr(strBuffer(index)) = vbNullChar Then Exit For
tmpString = tmpString & Chr(strBuffer(index))
Next index
tmpString = Trim(tmpString)
'**************************************************
'deallocate the memory and close the process handle
'**************************************************
result = VirtualFreeEx(pHandle, pStrBufferMemory, 0, MEM_RELEASE)
result = VirtualFreeEx(pHandle, pMyItemMemory, 0, MEM_RELEASE)
result = CloseHandle(pHandle)
If Len(tmpString) > 0 Then GetListviewItem = tmpString
End Function
-
Jul 7th, 2002, 01:43 AM
#3
Addicted Member
Might I just add that comparing a ListBox with a ListView is a bit like comparing a car with an aircraft!
Still, I understand and sympathise with Britomo's incredulity, which I remember having myself when I first crashed my PC trying the very same !!
Anyway, it's a good thing, especially if it makes you want to understand exactly why your initial attempt crashed out! Call this lesson "Foreign Process Data Extraction 101".
Once you've understood this, you should then be ready for the "FPDE 101" exam question:
==============================================
Q1. "How come it works for ListBox'es??? Shouldn't it fail for the very same reasons it fails for ListView's ????"
Discuss (max 1500 words)
==============================================
Q2. "Why is Windows programming so much fun????"
Give reasons!
==============================================
Dr Memory
Last edited by MathImagics; Jul 7th, 2002 at 01:55 AM.
"He's got a B.A. (in be-bop), a Ph.D. (in swing), he's a Master of Rhythm, he's the Rock'n'Roll king"  ("The Rock'n'Roll Doctor", Lowell George)
"If you push something hard enough, it will fall over" (Fudd's Third Law of Opposition)
-
Jul 7th, 2002, 02:28 AM
#4
Member
MathImagics:
hehe.. it was a fun (and challenging) problem when i was first faced with it, but the code was not all that difficult. main thing that i didnt understand (at the time), is why i was able to get the Listbox item text via SendMessage, but not the list view... I wasn't thinking about the whole foriegn process thing at the time.
Brimito -- if you want a hint as to what the anser to MathImagic's first question is, think about the origin of the ListView. The time it came into being (as a control) has something to do with the answer 
btw: way back when I was working on this, I found a very dated Microsoft Developer's Journal article that was *very* informative. does this publication still exist? It seemed like a *very* good resource for windows coding/api info.
-
Jul 7th, 2002, 07:48 PM
#5
Thread Starter
New Member
Thanks for replying 
Looking at that function you wrote hax0r, I'm completly lost . I could have a go at implementing it in my app, but I have no idea where to start or how it all works . I had no idea that this little app would get so complicated hehe. My knowledge of VB is pretty limited at the moment and I'm only just learning about API, which I understand alot better than I used to 
All this about writing to the other programs memory space is unfortunately waay beyond me . I see that the function is well commented, but I still do not understand how it would all fit in exactly. It would be good if you could explain a little more about. However, I don't expect you to, as I don't even know where to start with it. Spot the newbie
If I fail to get to grips with that function, then I think I might be able to get the items in the ListView 1 at a time. It would be a cumbersome way to go about it, but basically when a user double clicks on an item in the listview, another window open with the item text in a combobox. So I was thinking about sending BM_CLICK to the listview, then find the handle of the combo box and get the text from there, then closing that window and going back to the listview and doing the whole thing over again for the next item etc. Very long winded, but that's the only other way I can think of doing it.
I've tried sending BM_CLICK to the listview, but I couldn't get it to work. I can get it to work for commandbutton though.
Call PostMessage(button, BM_CLICK, 0, ByVal 0&)
Would I have to use SendInput for a listview instead or something¿
Also, the long winded workaround that I'm thinking of doing, how doable is it¿ I mean, would it take long to repeat that process for about 100 - 200 items in the listview and would the user still be able to use mouse and keyboard in another app¿
Thanks again for your time and advice, much appreciated
-
Jul 7th, 2002, 08:17 PM
#6
Member
You won't be able to get the items one at a time in the external listview. you have to understand process / memory bounds. sure, the GET_ITEM call of a listbox works with an external app, but the same is not the case when it comes to a listview, treeview, or any other control which did not exist under Windows 3.1. if you want the answer as to why this is the case, then do some research -- it will help you out in the long run 
in anycase, i think using the function is relatively self explanatory. you send in a handle to a listview, the process ID of the foreign executable, and the row/column you want the item text for. looking at your code, you have almost all of that information already -- have for maybe the process ID. do a bit of research and you'll find how you can obtain the process ID from an hWnd -- if you're still stuck, reply back and I'll help.
You wanted an explanation of how the function works -- well, here it goes :
basically, the function allocates an LV_ITEM structure (in 'C' speak), ie: notice that the pszText item is a long, and not a VB string variable. This is the case because relatively speaking, strings in C are arrays of characters, and by default - windows is expecting a pointer to an array or chars (thus the long). Also, since you need to send in the length of the LV_ITEM structure into the WriteProcessMemory call, you can't use an open ended / nondefined length such as an un-initialized Vb String.
Since the ListView you are querying is in an external process, the recieving program will not properly be able to process your SendMessage command since the memory location of the structure you are sending in (for it to fill out) resides outside of its own memory scope. Thus, you need to "create" the structure in its own memory scope so that it can properly "fill it in". After it is "filled in", you need to have windows re-create that strure within the memory scope of your application -- so you can read it.
Basically, the gist of it is that any given process *cannot* access/modify memory locations outside of its scope. The Listbox, Textbox and certain other controls which can be utilized with SendMessage and which existed under Windows 3.1 are exceptions to this rule. Do your homework and report back to me tomorrow with you answer as to why this is the case.
As it stands, you should be able to "copy/paste" my code into your program and make it do what you want it to -- not that I am advocating this approach towards VB coding, but it attempting to implement my code might serve as a learning experience for you.
I think that too often people who read these forums take things for granted, and consider themselves "experts" without knowing a damn **** about what they are copying/pasting.
- hax
-
Dec 12th, 2004, 05:19 AM
#7
Fanatic Member
Re: Get text from ListView in another app
I tried this function but it did not have any result. It only returned null strings .
Do you possibly know what went wrong ?
I got the window handle and the process id of an external program but it did
not return the contents of the listview item.
-
Dec 12th, 2004, 11:37 AM
#8
Member
Re: Get text from ListView in another app
If it is an owner drawn ListView you will not be able to retrive its contents.
-
Dec 13th, 2004, 04:57 AM
#9
Fanatic Member
Re: Get text from ListView in another app
 Originally Posted by hax0r
If it is an owner drawn ListView you will not be able to retrive its contents.
yes it is an owner drawn listview. why can't i read its contents ?
is there another way to do this ?
-
Dec 13th, 2004, 03:57 PM
#10
-
Dec 13th, 2004, 06:48 PM
#11
Frenzied Member
Re: Get text from ListView in another app
 Originally Posted by manavo11
If it's owner drawn it's subclassed. It won't process the message you send I think.
Negative. If something is subclassed, you can still get contents by subclassing it yourself.
:::`DISCLAIMER`:::
Do NOT take anything i have posted to be truthful in any way, shape or form.
Thank You!
--------------------------------
"Never heard about "hiking" poles. I usualy just grab a stick from the nature, and use that as a pole." - NoteMe
"Finaly I can look as gay as I want..." - NoteMe
Languages: VB6, BASIC, Java, C#. C++
-
Dec 13th, 2004, 08:30 PM
#12
Member
Re: Get text from ListView in another app
This is not necesarily true. Since the ListView is owner drawn, it is reposinble for painting its own contents. This totally *can* bypasses the 'ItemText' collection of the ListView. If the ListView is rendering a graphical representation of the text on screen and not exposing any events which can be used to retrieve the internal data, you are stuck. Once 'My List Item' is rendered graphically on screen, there is no real easy way to convert that graphical representation back to its constiuent text.
While its true you can subclass something via an external hook and trap its messages that doesn't really get you much when all you end up getting is WM_PAINTs.
-
Mar 16th, 2006, 11:51 AM
#13
New Member
Re: Get text from ListView in another app
I worked on something like this a ways back, and OpenProcess() failed everytime.
I tried the above function, and it fails at the OpenProcess() aswell
all the parameters are right, any ideas why it would be failing everytime?
-
Mar 16th, 2006, 08:31 PM
#14
Member
Re: Get text from ListView in another app
You probably do not have access to open the process. Are you a local administrator?
-
Mar 16th, 2006, 09:42 PM
#15
New Member
Re: Get text from ListView in another app
I am yes.
And the Process show's as my User in task manager.
-
Mar 28th, 2006, 06:57 PM
#16
New Member
Re: Get text from ListView in another app
Peace All
Haxor's script workrd for me but I had to go everytime to the the task manager and find the process Id of the main Process. or by using spy++. Some one else in the same Forum offerd this script to
Dim processID As Long
Dim proc As Long
'/// get the processID of the listview ...
GetWindowThreadProcessId(" handle to Listview here !!! " , processID)
'/// now you have the processID ...
proc = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE Or PROCESS_QUERY_INFORMATION , False, processID)
But This Script doesnt return the right Process ID fro some unkown reasons, can anyone give a hint
-
Jan 17th, 2008, 02:17 AM
#17
New Member
Re: Get text from ListView in another app
how can i grab listview in yahoo room !
in to my own list in vb form!?
-
Jun 18th, 2008, 09:21 AM
#18
Addicted Member
Re: Get text from ListView in another app
Anyone got a working example of this code in .NET 2005 as i cant seem to get mine to convert correctly?
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|