Mark S. Rasmussen improve.dk
Apr 04
2007

This time we want to retrieve the text from a given window, represented by a handle. Like last time, open an Internet Explorer instance. Now open Winspector and select the address field, ensure that it is the address field itself (class = Edit) and not the ComboBox that you select.

using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Globalization;

namespace Get_text_from_handle
{
	class Program
	{
		// These are two Win32 constants that we'll need, they'll be explained later.
		const int WM_GETTEXT		= 0x000D;
		const int WM_GETTEXTLENGTH = 0x000E;

		// The SendMessage function sends a Win32 message to the specified handle, it takes three
		// ints as parameters, the message to send, and to optional parameters (pass 0 if not required).
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, int lParam);

		// An overload of the SendMessage function, this time taking in a StringBuilder as the lParam.
		// Through the series we'll use a lot of different SendMessage overloads as SendMessage is one
		// of the most fundamental Win32 functions.
		[DllImport("User32.dll")]
		public static extern Int32 SendMessage(int hWnd, int Msg, int wParam, StringBuilder lParam);

		static void Main(string[] args)
		{
			// First, read the handle from the console, remember this has to be in HEX format!
			int handle = int.Parse(Console.ReadLine(), NumberStyles.HexNumber);

			// This is a bit tricky. To retrieve the text from a window, we have to know it's length beforehand.
			// This is because we have to send a StringBuilder of the correct length as a parameter. If it's too
			// small, it won't be able to contain the full text. If it's too large, it's inefficient. When using
			// the SendMessage function with the WM_GETTEXTLENGTH message, it returns the length of the
			// window text.
			int txtLength = SendMessage(handle, WM_GETTEXTLENGTH, 0, 0);

			// After having retrieved the length of the string, we create a StringBuilder to hold it.
			StringBuilder sb = new StringBuilder(txtLength + 1);

			// Sending the message WM_GETTEXT to the window, passing int he length of the text (the capacity
			// of the StringBuilder) as well as a reference to the StringBuilder will result in the
			// StringBuilder being filled up with the windows text.
			SendMessage(handle, WM_GETTEXT, sb.Capacity, sb);

			// Finally we'll write out the window text by ToString()'ing the StringBuilder.
			Console.Write(sb.ToString());
			Console.Read();
		}
	}
}

And the result:

Mark S. Rasmussen
I'm the CTO at iPaper where I cuddle with databases, mold code and maintain the overall technical & team responsibility. I'm an avid speaker at user groups & conferences. I love life, motorcycles, photography and all things technical. Say hi on Twitter, write me an email or look me up on LinkedIn.