Sorry but this seems neverending, I have not yet come accross a proper working example (code). Please somebody put up an example (code) that actually works! thankyou
Printable View
Sorry but this seems neverending, I have not yet come accross a proper working example (code). Please somebody put up an example (code) that actually works! thankyou
Yup, thats what I thought.
What have you tried that didn't work?
Also, if it's owner drawn it might not work...
I have tried everything, hax0rs function looked most promising but returns null strings. Its not owner drawn. This just simply cant be done, nobody can put up working code for this, only reaons why it wont work or code that doesnt work! sucks
You need to be a little more specific about what does not work.
I've read throught the other threads and simply stating that it returns null strings is not of any help.
Do you examine the return code from each API call to determine if any of your functions are returning an error?
The code posted does work, it is just not working in your situation so something specific about your program is not working.
Did you want to get the text of the listview item?
Using WriteProcessMemory and ReadProcessMemory works fine from VB.
From what i've read from others, they say you need to do it from within the external app's process memory. So I made this code that did just that. I tried it on Windows Explorer and it gave me the correct text.
i used c++ and vb.net
for the c++ dll:
now for the vb.net code that calls the dll function installHook():Code:#include "stdafx.h"
#include "Commctrl.h"
#pragma data_seg(".shared")
HWND _hTarget = 0;
HHOOK hook=0;
#pragma data_seg()
#pragma comment(linker, "/SECTION:.shared,RWS")
LVITEM *lvItem;
char lpText[255];
HINSTANCE hInst;
bool flag = true;;
//send LVM_GETITEMTEXT message from within external app's process
int getLVText(HWND hTarget)
{
lvItem = new LVITEM;
lvItem->iSubItem = 0;
lvItem->cchTextMax = 255;
lvItem->pszText = lpText;
int res = SendMessage(hTarget, LVM_GETITEMTEXT, 0, (long)lvItem);
if (res != 0)
{
flag = false;
MessageBox(NULL, lvItem->pszText, "", MB_OK); //messagebox shows the listview item string
return 1;
}
return 0;
}
BOOL APIENTRY DllMain( HANDLE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hInst = (HINSTANCE)hModule;
return TRUE;
}
LRESULT CALLBACK hookproc(int nCode, WPARAM wParam, LPARAM lParam)
{
if(flag) //I put the flag so it only calls getLVText once
{
getLVText(_hTarget);
}
return ::CallNextHookEx(hook, nCode, wParam, lParam);
}
//these codes injects the dll into external app's process
__declspec(dllexport) int _stdcall installHook(HWND hTarget)
{
_hTarget = hTarget;
DWORD tid;
tid = ::GetWindowThreadProcessId(hTarget, 0);
hook = ::SetWindowsHookEx(WH_GETMESSAGE, hookproc, hInst, tid);
if (hook != NULL)
return 1;
return 0;
}
VB Code:
Public Declare Function installHook Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal hwnd As Integer) As Integer Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim hTarget As Integer 'the handle to the target ListView control, Im sure you could implement the code to get the handle Dim res As Integer = installHook(hTarget) End Sub
I hope getting the text of the listview items is what you wanted because it took me a while to do this. This is probably not the exact code you'll be using in your program, but it should give you an idea of how to get the text of the listview item.
Moeur, was that last comment of yours for me?
My last comment was for anyone looking to do this.
You have shown one way to do it and I was commenting that the original way works well too and does not require C++.
oh. Well, I was just curious how that other way works. If you write the structure in the external process, then you sendmessage() using the pointer that you get from the writeprocessmemory(), which process memory is that pointer pointing to? The calling process or the external process? I'm a bit confused. When I sendmessage(), lets say WM_SETTEXT, the pointer to the buffer containing the string is pointing to an address in the calling process. But the method with WriteProcessMemory() appear to be pointing at an address in the external process.
You are correct, when you call SendMessage with the WM_SETTEXT message, the operating system recognizes the message and marshals the data for you from one process to the next as required.
User-defined messages are not marshalled since the OS does not know about them (since they are user defined).
Many messages that are specific to certain controls like the listview and RichTextbox are user-defined messages and the OS does not marshal them for you.
benmartin101, any chance of the actual dll? and also the code for vb where u put the vb.net code in the button. Thanks, sorry.. know im asking alot!
hum..
Dim res As Integer = installHook(hTarget)
Integer ? should it be string ?
Also the window handle is integar shouldnt that be long
I attached the project with the dll.
Here is the vb.net code to call and use the dll.
VB Code:
Imports System.Runtime.InteropServices Public Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer Public Const WM_CHAR = &H102 Public Declare Function installHook Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal hwnd As Integer, ByVal vbhwnd As Integer) As Integer Public Declare Function getItemText Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal index As Integer) As IntPtr Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim res As Integer = installHook(listViewHandle, Me.Handle.ToInt32) PostMessage(child, WM_CHAR, 0, 0) End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Dim strPtr As IntPtr = getItemText(itemIndex) '0 based Dim str As String = Marshal.PtrToStringAnsi(strPtr) MsgBox(str) End Sub
Thanks for your effort but I am so confused, forgive my ignorance.
Ok first of all why is your api " hwnd As Integer" and not long????
Also on the first button click, what is:
"PostMessage(child, WM_CHAR, 0, 0) "
I don't see a child variable anywhere... whats going on there??
Just everything about that code doesnt make any sense to me, maybe its cause its in .net
Can anybody transfer this to vb???? belive me I have tried
its integer instead of long because in vb6, long is 4 bytes, while long in vb.net is 8 bytes. To make it work, substitute long with vb.net's integer, which is 4 bytes. The "child" part, you should replace that with the handle of your target listview.
I made changes to dll, so I attach new version.
Here is vb6 code:
VB Code:
Private Const WM_CHAR = &H102 Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long 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 installHook Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal hwnd As Long) As Long Private Declare Function getItemText Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" (ByVal index As Long) As Long Private Declare Function getItemCount Lib "C:\Program Files\Microsoft Visual Studio\MyProjects\getListView\Debug\getListView.dll" () As Long Private Declare Function lstrcpy Lib "kernel32" Alias "lstrcpyA" ( _ ByVal lpString1 As String, _ ByVal lpString2 As Long _ ) As Long Private Declare Function lstrlen Lib "kernel32" Alias "lstrlenA" ( _ ByVal lpString As Long _ ) As Long Private Sub Command1_Click() Dim lvHwnd As Long 'handle to listview Dim res As Integer res = installHook(lvHwnd) PostMessage lvHwnd, WM_CHAR, 0, 0 'this triggers dll to load End Sub Private Sub Command2_Click() Dim lpString As Long Dim strVal As String Dim lenstr As Long Dim itemCount As Long itemCount = getItemCount() 'to get total item in listview lpString = getItemText(0) 'to get text of item; 0-based lenstr = lstrlen(lpString) + 1 strVal = String(lenstr, 0) lstrcpy strVal, lpString MsgBox (strVal) End Sub
Thanks again for all your effort, but it just doesnt seem to work.. it doesnt even return the amount in the listview (returns 0)
can you post the vb code that you are running?
Exact same vb code you posted, except i put:
VB Code:
Private Sub Command1_Click() Dim lvHwnd As Long 'handle to listview lvHwnd = whatever the handle is Dim res As Integer res = installHook(lvHwnd) PostMessage lvHwnd, WM_CHAR, 0, 0 'this triggers dll to load End Sub
And of course changed path to the dll!
I attached a vb project that should let you understand how to make it work. Try it on a windows explorer folder and you'll see it works.(Make sure you drag that icon to the "listview" window and not just the parent window) If you use this program and still not get the listview items, then that listview class your trying to access is different from what i've been trying to access.
Whoooo hoooooooooooo after some messing got it to work!!!! wow I have to say a huge well done to you, I never thought I would see this working (getting listview items)
Heres a few more questions... (do forgive me)
Ok firstly how can I make the dll smaller?
Also, is there a away to get the tooltip text of the listview item as well as the text???
Can you get the listviews item image index ?
Thanksyou so much for all your time and effort and skill!!!!!
I have a question. What exactly are you trying to make?
Nothing really, I have just been looking into this for a year.. just would like to see how much you can actually do/get from a listview
well, if you want to know more about it, then you may want to look into this site:
http://msdn.microsoft.com/library/de...titemcount.asp
and about the dll, I don't know of a way to make it smaller.
Ok, once thing I noticed is if the listview updates/has more/less items.. your code grabs the old items even if u restart ur program
Yes, that's a bug that i've noticed. If you restart your computer, it goes back to normal. Can't really tell why, but as long as you get the idea of getting the item's text.
Nice work Ben!
Here is how you can do it without the dll.
Thanks for that moeur but having problems with the hex part
how are you getting the hWnd of your listview?
If you are using spy++ then the hWnd is in Hex you can just enter that number.
Sorry moeur just used spy++ and it works great, the above bug doesnt happen either (not getting new items), great code and thankyou. Do you know much about the lvmgettooltips? I did a search and only found one post about it (a post I made a while ago), just wondering how to get the items tooltip text and even get the icon it uses maybe.
I tried both the programs posted, they both work for me.. I was wondering if theres anyway to use them on other applications that have things that look like listboxes, but apparently they arent... they dont have the class SystemListView or whatever, and niether code workson them..
The classname of the 'listbox' i want this to work on is "Afx:400000:28:10011:0:0" if that helps
I think 'listbox' is different from 'listview'.
Sorry I meant listview I was probably just using the wrong term.. how can I tell what it is for sure?
thread hijaCK!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Afx controls were created before Windows existed. Instead of using a Windows text property, the text is owner-drawn by the control. As far as Windows is concerned, the control has no text--just a picture that happens to look to you like text. I've seen attempts to monitor windows messages to try to detect what characters are being written, but nothing successful. As far as I know, the only way to read the text of an Afx control is using mouse or keyboard events to raise a copy event in the Afx control so that you can get the text from the clipboard or through optical character recognition. :sick:Quote:
Originally Posted by bail3yz
Many thanks for sharing this code. I tried to drag the icon to external listview to obtain the list but i get the follwoing error:Quote:
Originally Posted by benmartin101
http://i5.photobucket.com/albums/y18...7/38f1fdaa.jpg
and it is pointing to
I be happy if u tell me how to fix it.ThanksCode:Screen.MouseIcon = LoadPicture("C:\Program Files\Microsoft Visual Studio\VB98\protune.ico")
could u let me know what is Enter hWnd of LV in Hex for the any external listview that i want obtain its data? how to get it ? Furthermore, where i will save the grabbed viewlist items?ThanksQuote:
Originally Posted by moeur
It means you don't have that file. Just change the path to any .ico file that is in your machine. Also, make sure you have the dll that is required. It should be somewhere in this thread. The zip file right before vbListView.zip. You may have to change the dll import path in the vb code to wherever you end up saving the dll.
to get handle(hWnd), you may want to look into api functions FindWindow and FindWindowEx
Quote:
Originally Posted by moeur
Question about GetLVItem.zip which is without dll
Thank u for sharing this code. I tried your project ( GetLVItem.zip) but i get the following error and nothing happens
http://i5.photobucket.com/albums/y18...od007/dam3.jpg
http://i5.photobucket.com/albums/y18...od007/dam2.jpg
could u tell me how to fix it and where the out put will will shown?Thanks
benmartin101 i still could not the the version of program that works without dll.Also i have another question how i can click and move down an external listview ? What i mean when i high light first item in an external listview i want vb goes and clicks on it and then jump to next value and goes downs the list this way. I be happy if u tell me how to achive this .Thanks and waiting for u reply.
I get errors when running the code from the free memory routinesQuote:
Originally Posted by moeur
Error releasing string buffer memory: 87 (&H57): The parameter is incorrect.
Error releasing LVITEM structure memory: 87 (&H57): The parameter is incorrect.
It does return the correct data but eventually crashes the program with the syslistview32 control.
I did not make any changes to the code in he zip file.
Thanks.
I solved the problem, or rather I found where someone else had a similar problem. I have no idea why this works so if someone knows please fill me in so I know when this has to be done. It seems that the constant defined as MEM_RELEASE = &H8000 has to be MEM_RELEASE = &H8000& with the trailing &. I don't know why the other constants seem to work fine without the trailing &. Here is the section of code changed.Quote:
Originally Posted by ed08724
Private Const MEM_COMMIT = &H1000
Private Const MEM_RESERVE = &H2000
Private Const MEM_DECOMMIT = &H4000
Private Const MEM_RELEASE = &H8000&
Two threads from 2006 and lots of posts. Is it solved or not. If not, here is how to do it.
1. Open a new standard exe project with Form1.
2. Add a listbox List1 and a commanbutton Command1 to the form.
3. Paste the code below
4. Replace "WindowName" with actual window name
5. Replace "fullpath to listview.exe" with actual string
This will start the listview exe on form load. Pushing commandbutton will retrieve all listview items text.
Hope this will solve this problem.
Code:Option Explicit
Private Const LVIF_TEXT As Long = &H1
Private Const LVM_FIRST As Long = &H1000
Private Const LVM_GETITEM As Long = (LVM_FIRST + 5)
Private Const LVM_SETITEM As Long = (LVM_FIRST + 6)
Private Const LVM_GETITEMCOUNT As Long = (LVM_FIRST + 4)
Private Const MEM_COMMIT As Long = &H1000
Private Const PAGE_READWRITE As Long = &H4
Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000
Private Const SYNCHRONIZE As Long = &H100000
Private Const PROCESS_ALL_ACCESS As Long = (STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF)
Private Const MEM_RELEASE As Long = &H8000
Private Type LVITEM
mask As Long
iItem As Long
iSubItem As Long
state As Long
stateMask As Long
pszText As Long 'Notice not string but long
cchTextMax As Long
iImage As Long
lParam As Long
iIndent As Long
End Type
Private Declare Function OpenProcess Lib "kernel32.dll" ( _
ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32.dll" ( _
ByVal hProcess As Long, _
ByRef lpBaseAddress As Any, _
ByRef lpBuffer As Any, _
ByVal nSize As Long, _
ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32.dll" ( _
ByVal hProcess As Long, _
ByRef lpBaseAddress As Any, _
ByRef lpBuffer As Any, _
ByVal nSize As Long, _
ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32.dll" ( _
ByVal hwnd As Long, _
ByRef lpdwProcessId As Long) As Long
Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" ( _
ByVal lpClassName As Long, _
ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32.dll" Alias "FindWindowExA" ( _
ByVal hwndParent As Long, _
ByVal hwndChildAfter As Long, _
ByVal lpszClass As String, _
ByVal lpszWindow As Long) As Long
Private Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" ( _
ByVal hwnd As Long, _
ByVal wMsg As Long, _
ByVal wParam As Long, _
ByVal lParam As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32.dll" ( _
ByVal hProcess As Long, _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal flAllocationType As Long, _
ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32.dll" ( _
ByVal hProcess As Long, _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal dwFreeType As Long) As Long
Private Declare Function CloseHandle Lib "kernel32.dll" ( _
ByVal hObject As Long) As Long
Private Declare Function TerminateProcess Lib "kernel32.dll" ( _
ByVal hProcess As Long, _
ByVal uExitCode As Long) As Long
Dim hProcess As Long
Private Sub Command1_Click()
Dim hndl As Long
Dim hListView As Long
Dim lpdwProcessId As Long
Dim pMem As Long
Dim lvi As LVITEM
Dim lpNumberOfBytesWritten As Long
Dim i As Long
Dim cItems As Long
Dim txt As String
Dim pTxt As Long
'Get the handle of listview control
hndl = FindWindow(0, "WindowName")
hListView = FindWindowEx(hndl, 0, "SysListView32", 0)
'Retrieve a handle of the listview control process
GetWindowThreadProcessId hListView, lpdwProcessId
hProcess = OpenProcess(PROCESS_ALL_ACCESS, False, lpdwProcessId)
'Allocate memory in listview process memory space for the LVITEM structure and listitem text
pMem = VirtualAllocEx(hProcess, 0, Len(lvi), MEM_COMMIT, PAGE_READWRITE)
pTxt = VirtualAllocEx(hProcess, 0, 256, MEM_COMMIT, PAGE_READWRITE)
'Retrieve number of listview items
cItems = SendMessage(hListView, LVM_GETITEMCOUNT, 0, 0)
'Fill a LVITEM structure with values
lvi.mask = LVIF_TEXT
lvi.cchTextMax = 256
lvi.pszText = pTxt 'This is a pointer to the address where item text will be hold
'Allocate space for a string
txt = Space(256)
For i = 0 To cItems - 1
'Add item index to structure
lvi.iItem = i
'Transfer the structure to allocated memory in listview memory space
WriteProcessMemory hProcess, ByVal pMem, lvi, Len(lvi), lpNumberOfBytesWritten
'Send message to get listview item [i]. Result hold in LVITEM strucktur at address pMem
SendMessage hListView, LVM_GETITEM, 0, ByVal pMem
'Transfer the item text from allocated memory at pTxt to txt space in this app process memory
ReadProcessMemory hProcess, ByVal pTxt, ByVal txt, 256, lpNumberOfBytesWritten
List1.AddItem txt
Next i
'Free allocated memory
VirtualFreeEx hProcess, pMem, Len(lvi), MEM_RELEASE
VirtualFreeEx hProcess, pTxt, 256, MEM_RELEASE
End Sub
Private Sub Form_Load()
Shell "fullpath to listview.exe"
End Sub
Private Sub Form_Terminate()
TerminateProcess hProcess, 0
CloseHandle hProcess
End Sub
It doesn't work on mine or at least not for long because of the memory leak which I described above on how to fix. I don't know why I have to do this or why others don't seem to have the same problem. I would be interested to know if you debug.print the results from VirtualFreeEx hProcess, pMem, Len(lvi), MEM_RELEASE
to see if it runs w/o error.
like:
debug.print VirtualFreeEx(hProcess, pMem, Len(lvi), MEM_RELEASE)
debug.print VirtualFreeEx(hProcess, pTxt, 256, MEM_RELEASE)
Quote:
Originally Posted by minor28
You are right I was too quick writing. I did commit the memory space and thus must decommit it.
This is how it is done
Code:VirtualFreeEx hProcess, pMem, 0, MEM_DECOMMIT
VirtualFreeEx hProcess, pTxt, 0, MEM_DECOMMIT
It seems that on Win98/ME &H8000 returns 32768 but on NT/XP it returns -32768 but &H8000& returns 32768 on both. So the answer is to use the trailing & on any numbers greater than &H7FFF. (Keywords syslistview32 memory leakage memory creep vb6 vb MEM_RELEASE)Quote:
Originally Posted by ed08724
Hi everyone,
I'm sort of new here, although i've been a post reader for a while i've not done any posting my self.
I'm wondering if I may be able to adapt moeurs code to stop an external app from closing without using a seperate dll.
Maybe I'm in the wrong place and this code won't work for me but maybe someone can help me out?
I have posted here explaining what I need to do, and source code of my subclass control and test app (which is a bit untidy but works when referenced in a vb app :)):
http://www.vbforums.com/showthread.p...07#post3193507
PLEASE HELP ME :confused:
If you can find the window message that hits when an application is closing then you can stop that. But i don't know the name of this message.
thanks sapator, I've built a small activeX dll which can get the handle under mouse, get parent and subclass to stop closing. When I reference my dll in another vb6 app it works but when I try to subclass an external app (none vb) it doesn't.Quote:
Originally Posted by sapator
My dll can also be used to monitor system messages (a bit like spy) because the form I'm trying to subclass closes when it loses focus which makes it impossible to watch with spy.
My first post has the link to my thread which explains a what I need to do and has the source and test app for my dll.
The messages i'm trying to stop are WM_CLOSE and WM_SYSCOMMAND with param SC_CLOSE for now.
I don't want to clutter this thread with too much non-related content so if you can help me please can you post in my thread:)