From: SQACSharp on
I'm trying to get the control name of an editbox in another window.

The following code set the value "MyPassword" in the password EditBox
but it fail to return the control name of the EditBox. I'm sure the
problem is the way i'm using the sendmessage API, the return string and
the lParam return 0....is anybody have a clue? any sendmessage api
expert here?

[DllImport("User32.dll")]
public static extern Int32 FindWindow(String lpClassName,String
lpWindowName);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SendMessage(int hWnd, int msg, int wParam,
IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr
childAfter, string className, string windowTitle);
[DllImport("user32.dll")]
public static extern UInt32
RegisterWindowMessage([MarshalAs(UnmanagedType.LPTStr)] String
lpString);
// ....

int hwnd = 0;
IntPtr hwndChild = IntPtr.Zero;
hwnd = FindWindow(null, "Login");
hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "TEdit", "");
SetControlText((int)hwndChild, WM_SETTEXT, 0, "MyPassword");

//the following is not working as expected to get the control name
uint SendMsg;
SendMsg = RegisterWindowMessage("WM_GETCONTROLNAME");
long ReturnMsg;
IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
Marshal.WriteIntPtr(ptr, IntPtr.Zero);
ReturnMsg=SendMessage((int)hwndChild, (int)SendMsg, 65536, ptr);
IntPtr CtrlName = Marshal.ReadIntPtr(ptr);
MessageBox.Show(CtrlName.ToString());
MessageBox.Show(ReturnMsg.ToString());
Marshal.FreeCoTaskMem(ptr);

From: SQACSharp on
Still need help :(

From: Peter Duniho on
"SQACSharp" <lsdisciples(a)hotmail.com> wrote in message
news:1162666690.828659.259590(a)i42g2000cwa.googlegroups.com...
> Still need help :(

I still don't know the answer.


From: Willy Denoyette [MVP] on

"SQACSharp" <lsdisciples(a)hotmail.com> wrote in message
news:1162596214.680573.161130(a)h54g2000cwb.googlegroups.com...
| I'm trying to get the control name of an editbox in another window.
|
| The following code set the value "MyPassword" in the password EditBox
| but it fail to return the control name of the EditBox. I'm sure the
| problem is the way i'm using the sendmessage API, the return string and
| the lParam return 0....is anybody have a clue? any sendmessage api
| expert here?
|
| [DllImport("User32.dll")]
| public static extern Int32 FindWindow(String lpClassName,String
| lpWindowName);
| [DllImport("user32.dll", CharSet = CharSet.Auto)]
| public static extern int SendMessage(int hWnd, int msg, int wParam,
| IntPtr lParam);
| [DllImport("user32.dll", SetLastError = true)]
| public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr
| childAfter, string className, string windowTitle);
| [DllImport("user32.dll")]
| public static extern UInt32
| RegisterWindowMessage([MarshalAs(UnmanagedType.LPTStr)] String
| lpString);
| // ....
|
| int hwnd = 0;
| IntPtr hwndChild = IntPtr.Zero;
| hwnd = FindWindow(null, "Login");
| hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "TEdit", "");
| SetControlText((int)hwndChild, WM_SETTEXT, 0, "MyPassword");
|
| //the following is not working as expected to get the control name
| uint SendMsg;
| SendMsg = RegisterWindowMessage("WM_GETCONTROLNAME");
| long ReturnMsg;
| IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
| Marshal.WriteIntPtr(ptr, IntPtr.Zero);
| ReturnMsg=SendMessage((int)hwndChild, (int)SendMsg, 65536, ptr);
| IntPtr CtrlName = Marshal.ReadIntPtr(ptr);
| MessageBox.Show(CtrlName.ToString());
| MessageBox.Show(ReturnMsg.ToString());
| Marshal.FreeCoTaskMem(ptr);
|

You can't use locally allocated heap buffers when the HWND of the window you
send the GETCONTROLNAME to, belongs to a thread in another process. You have
to allocate the buffer in the other process memory space using OpenProcess
followed by VirtualAllocEx, after calling SendMessage you'll have to read
the buffer using ReadProcessMemory followed by a call to VirtualFreeEx.
Note also that you should carefully check the return values of the API's,
and beware that the other process must run in the same winsta/desktop pair,
that is, in the same logon session.

Willy.


From: SQACSharp on
Your help is really appreciated Willy since i'm trying to do this since
almost a week :(

Ok i try to understand how to use the openProcess, VirtualAllocEx,
ReadProcessMemory and VirtualFreeEx to solve my problem but i'm not
sure exactly how i'm suppose to use the ReadProcessMemory to retreive
the controlname returned by my sendmessage API call..This is what it
look like after spending 3-4 more hours on that :

System.Diagnostics.Process.Start("\"C:\\MyApplication.exe\"", "");
int hwnd = 0;
IntPtr hwndChild = IntPtr.Zero;
hwnd = FindWindow(null, "Login");
hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "TEdit", "");
SetControlText((int)hwndChild, WM_SETTEXT, 0, "MyPassword!");

// The following is my nightmare to get the controlname....still not
working :(
System.Diagnostics.Process[] processes;
processes = System.Diagnostics.Process.GetProcesses();
uint ProcessId;
IntPtr hProcess = IntPtr.Zero;
const uint PROCESS_ALL_ACCESS = (uint)(0x000F0000L | 0x00100000L |
0xFFF);
foreach (System.Diagnostics.Process instance in processes)
{
if (instance.ProcessName == "MyApplication")
{
ProcessId = (uint)instance.Id;
hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0,
(uint)instance.Id);
}
}
if (hProcess == IntPtr.Zero)
throw new ApplicationException("Failed to access process");
const int dwBufferSize = 1024;
const uint MEM_COMMIT = 0x1000;
const uint MEM_RELEASE = 0x8000;
const uint PAGE_READWRITE = 0x04;
IntPtr lpRemoteBuffer = IntPtr.Zero;
IntPtr lpLocalBuffer = IntPtr.Zero;
IntPtr threadId = IntPtr.Zero;
lpLocalBuffer = Marshal.AllocHGlobal(dwBufferSize);
lpRemoteBuffer = VirtualAllocEx(hProcess, IntPtr.Zero, dwBufferSize,
MEM_COMMIT, PAGE_READWRITE);
if (lpRemoteBuffer == IntPtr.Zero)
throw new SystemException("Failed to allocate memory in remote
process");
Int32 SendMsg;
SendMsg = RegisterWindowMessage("WM_GETCONTROLNAME");
long ReturnMsg;
IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
Marshal.WriteIntPtr(ptr, IntPtr.Zero);
MessageBox.Show(SendMsg.ToString());
ReturnMsg = SendMessage((int)hwndChild, SendMsg, 65536,
lpRemoteBuffer);
bool bSuccess;
bSuccess = ReadProcessMemory(hProcess, lpRemoteBuffer, lpLocalBuffer,
dwBufferSize,IntPtr.Zero);
if (!bSuccess)
throw new SystemException("Failed to read from process memory");
string retval;
retval = Marshal.PtrToStringAnsi(lpRemoteBuffer);
MessageBox.Show(retval); //This is not working....how I'm suppose to
read the string value returned by my sendmessage???


Willy Denoyette [MVP] wrote:
> "SQACSharp" <lsdisciples(a)hotmail.com> wrote in message
> news:1162596214.680573.161130(a)h54g2000cwb.googlegroups.com...
> | I'm trying to get the control name of an editbox in another window.
> |
> | The following code set the value "MyPassword" in the password EditBox
> | but it fail to return the control name of the EditBox. I'm sure the
> | problem is the way i'm using the sendmessage API, the return string and
> | the lParam return 0....is anybody have a clue? any sendmessage api
> | expert here?
> |
> | [DllImport("User32.dll")]
> | public static extern Int32 FindWindow(String lpClassName,String
> | lpWindowName);
> | [DllImport("user32.dll", CharSet = CharSet.Auto)]
> | public static extern int SendMessage(int hWnd, int msg, int wParam,
> | IntPtr lParam);
> | [DllImport("user32.dll", SetLastError = true)]
> | public static extern IntPtr FindWindowEx(IntPtr parentHandle, IntPtr
> | childAfter, string className, string windowTitle);
> | [DllImport("user32.dll")]
> | public static extern UInt32
> | RegisterWindowMessage([MarshalAs(UnmanagedType.LPTStr)] String
> | lpString);
> | // ....
> |
> | int hwnd = 0;
> | IntPtr hwndChild = IntPtr.Zero;
> | hwnd = FindWindow(null, "Login");
> | hwndChild = FindWindowEx((IntPtr)hwnd, IntPtr.Zero, "TEdit", "");
> | SetControlText((int)hwndChild, WM_SETTEXT, 0, "MyPassword");
> |
> | //the following is not working as expected to get the control name
> | uint SendMsg;
> | SendMsg = RegisterWindowMessage("WM_GETCONTROLNAME");
> | long ReturnMsg;
> | IntPtr ptr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
> | Marshal.WriteIntPtr(ptr, IntPtr.Zero);
> | ReturnMsg=SendMessage((int)hwndChild, (int)SendMsg, 65536, ptr);
> | IntPtr CtrlName = Marshal.ReadIntPtr(ptr);
> | MessageBox.Show(CtrlName.ToString());
> | MessageBox.Show(ReturnMsg.ToString());
> | Marshal.FreeCoTaskMem(ptr);
> |
>
> You can't use locally allocated heap buffers when the HWND of the window you
> send the GETCONTROLNAME to, belongs to a thread in another process. You have
> to allocate the buffer in the other process memory space using OpenProcess
> followed by VirtualAllocEx, after calling SendMessage you'll have to read
> the buffer using ReadProcessMemory followed by a call to VirtualFreeEx.
> Note also that you should carefully check the return values of the API's,
> and beware that the other process must run in the same winsta/desktop pair,
> that is, in the same logon session.
>
> Willy.