.NET Framework - Problem using SendMessage in C# to get values of a ListBox on other application

Asked By Christian Berczely on 31-Mar-11 03:21 PM
I am using C# to build an application that gets values of a ListBox
that is in another application.

Here, hListBox is the handle to the ListBox running in the other

I am using SendMessage(hListBox, LB_GETCURSEL, IntPtr.Zero,
IntPtr.Zero) to get the current selected item from this ListBox. This
works well.

Then when I try to get the length and text it does not work.

This is what I have used to get the text: SendMessage(hListBox,
LB_GETTEXT, new IntPtr(pos), ipRemoteBuffer);

Do I need also to call VirtualAllocEx to create a text buffer on the
other application's space?
Then use ReadProcessMemory to read this out?

I have created a .net VC application that has the ListBox within the
same app where by code is, and this works. So I think the issue is on
getting the text from an external application...

I would really appreciate some sample code.

Peter Duniho replied to Christian Berczely on 31-Mar-11 08:57 PM
Windows will marshal WM_GETTEXT for you.  I do not know about LB_GETTEXT.
it is possible you need to allocate shared memory the other process can
write and which you can read.  I have also read that if the ListBox has
the LBS_HASSTRINGS style, it should work and otherwise it will not (and
that is probably true regardless of cross-process or not).

it is also possible your p/invoke declaration is incorrect.  .NET will
have to marshal any string declared in the p/invoke method.  If you are
instead passing an IntPtr, then you have to make sure you know how to
interpret it.

Without a proper concise-but-complete code example, that is about as
specific as I can offer in the way of comments.

Christian Berczely replied to Peter Duniho on 02-Apr-11 12:04 AM
Here is the code:

public const int LB_GETTEXT = 0x0189;
public const int LB_GETTEXTLEN = 0x018A;
public const int LB_GETCURSEL = 0x0188;
public const int LB_GETCOUNT = 0x018B;

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError =
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr
wParam, IntPtr lParam);

[DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError =
private static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr
wParam, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lParam);

private void test(IntPtr hwnd_listbox)
// hwnd_listbox is from a ListBox that is in another application

int count = (int)SendMessage(hwnd_listbox, LB_GETCOUNT,
IntPtr.Zero, IntPtr.Zero);  // this works, so hwnd_listbox is correct

int pos = (int)SendMessage(hwnd_listbox, LB_GETCURSEL,
IntPtr.Zero, IntPtr.Zero);  // this works

int len = (int)SendMessage(hwnd_listbox, LB_GETTEXTLEN,
(IntPtr)pos, IntPtr.Zero);  // wrong: returns 4

StringBuilder sbTxt = new StringBuilder(len + 1);
SendMessage(hwnd_listbox, LB_GETTEXT, (IntPtr)pos, sbTxt); //
wrong: returns garbage

string text = sbTxt.ToString();

What could be wrong?
Peter Duniho replied to Christian Berczely on 02-Apr-11 02:14 AM
Any number of things, including but not limited to the things I already
mentioned in my previous reply.