Solved

Get text from external window control

Posted on 2010-09-03
19
1,440 Views
Last Modified: 2013-12-17
Hello,

I want to get text contents from Windows Live Messager IM Window using API.
I have tried GetWindowText API, but it's not working.
0
Comment
Question by:Mohamed Abowarda
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 6
  • 5
  • 5
  • +2
19 Comments
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 33603535
it won't work surely as it is different process and you can't just pass anything more complex than simple types like integers and so forth because it would involve pointers which are different in different processes' memory space.

in order to achieve what you want you could try few things. the following link briefly describes them all:

http://en.wikipedia.org/wiki/DLL_injection

there is a chapter in Windows Internals books for that usually (eg Advanced Windows by Jeffrey Richter)

Here is some tutorial, but you can google for more:

http://www.codeproject.com/kb/dll/DLL_Injection_tutorial.aspx

0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 33603615
@alexey_gusev: I was not looking for DLL Injection, I just want to get the contents of a text box from another process using API.

Thanks,
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 33603642
I looked at the version I have and the window is DirectHWNDUI which means the standard windows messaging won't work on these windows.
You have to use IAccessible Interface to get information about this window. I can't provide you with code just point you in the right direction.
IAccessible Interface
http://msdn.microsoft.com/en-us/library/accessibility.iaccessible.aspx 
Client Functions
http://msdn.microsoft.com/en-us/library/dd742692(v=VS.85).aspx
0
PeopleSoft Has Never Been Easier

PeopleSoft Adoption Made Smooth & Simple!

On-The-Job Training Is made Intuitive & Easy With WalkMe's On-Screen Guidance Tool.  Claim Your Free WalkMe Account Now

 
LVL 38

Expert Comment

by:puppydogbuddy
ID: 33603650
See this link:
           http://cuinl.tripod.com/Tips/wincaption.htm
I think the code provided will enable you to capture the caption and thread id of the window you have your cursor pointing at.  You might be able to adapt this code to your needs by adding code that will set focus to the live messenger window.

Hope this helps.
0
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 33603664
ok, if you don't want DLL injection, please enjoy reading MSDN for that:

http://msdn.microsoft.com/en-us/library/ms633520(VS.85).aspx

especially this paragraph:
======================
Remarks
To retrieve the text of a control in another process, send a WM_GETTEXT message directly instead of calling GetWindowText.
======================
0
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 33603706
and here's the rough example of how to do it:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace GetWndText
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        const uint WM_GETTEXT = 0x000D;

        [DllImport("user32.dll")]
        public static extern int SendMessage(IntPtr hWnd, uint Msg, uint wParam, IntPtr lParam);

        private void button1_Click(object sender, EventArgs e)
        {
            IntPtr buffer = Marshal.AllocHGlobal(256);
            int res = SendMessage((IntPtr)Convert.ToInt32(textBox1.Text, 16), WM_GETTEXT, 256, buffer);
            string text = Marshal.PtrToStringAnsi(buffer);
            Marshal.FreeHGlobal(buffer);
            textBox2.Text = text;
        }
    }
}

Open in new window

0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 33603721
Unfortuanetley guys you can't use standard windows messages for these types of windows :(
You have to user IAccessible Interface if you have the Windows SDK or Accessible SDK you can use the Inspector (similar to Spyxxx.exe) but for IAccessible windows.
Typical location:
"C:\Program Files\Microsoft SDKs\Windows\v7.0\Bin\Inspect.exe"

msn.png
0
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 33603761
hence I was suggesting dll injection or hooking :)
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 33603783
I think there is way which is used by "Inspect.exe" to retrieve this information without DLL Injection.
0
 
LVL 24

Expert Comment

by:alexey_gusev
ID: 33603944
you can set a hook, without actual dll injecting
0
 
LVL 8

Expert Comment

by:Gururaj Badam
ID: 33606148
--> I have tried GetWindowText API, but it's not working. <--

What's the behavior here? do you actually get any text frm GetWindowText call?
0
 
LVL 38

Expert Comment

by:puppydogbuddy
ID: 33606564
see comment from alexy_gusev    09/04/10 ID#33603664
======================
Remarks
To retrieve the text of a control in another process, send a WM_GETTEXT message directly instead of calling GetWindowText.
======================
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 33607134
@Novice_Novice: 'GetWindowText' works well to get text from any window, not from external window control, sending WM_GETTEXT message works great to get external control text, but the problem here is that it's not working in Windows Live Messenger IM Window.
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 33607182
The message would only work for the caption/title of the window and nothing more than that. You need to use the IAccessible Interface if you want information from DirectUIHWND classes. http:#33603642
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 33607351
@egl1044: I think it will be better if you give example.
0
 
LVL 29

Accepted Solution

by:
nffvrxqgrcfqvvc earned 500 total points
ID: 33607987
Uhh.. I didn't really want to get into this since it had to be done from scratch but I had some free time to play.
Under Projects > Add Reference > .NET Tab
   Add reference to: Accessibility
Then try something like this...

Imports System.Runtime.InteropServices

Public Class Form1
    <DllImport("user32.dll", ExactSpelling:=False, SetLastError:=True, CharSet:=CharSet.Unicode)> _
    Public Shared Function FindWindowEx(ByVal hwndParent As IntPtr, _
                                        ByVal hwndChildAfter As IntPtr, _
                                        ByVal lpszClass As String, _
                                        ByVal sWindowTitle As String) As IntPtr
    End Function

    <DllImport("oleacc.dll", ExactSpelling:=True, SetLastError:=True)> _
    Public Shared Function AccessibleObjectFromWindow(ByVal hWnd As IntPtr, _
                                                      ByVal dwObjectID As Integer, _
                                                      ByRef refID As Guid, _
                                                      ByRef ppvObject As Accessibility.IAccessible) As Integer
    End Function

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        GetMsnInputText
    End Sub

    Public Sub GetMsnInputText()
        'egl1044
        Dim acc As Accessibility.IAccessible = Nothing
        Dim acc2 As Accessibility.IAccessible = Nothing
        Dim accMsnName As String = String.Empty
        Dim accMsnValue As String = String.Empty
        Dim msnIMWindow As IntPtr = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "IMWindowClass", Nothing)
        Dim msnIMWindowBar As IntPtr = FindWindowEx(msnIMWindow, IntPtr.Zero, "IM Window Native WindowBar Class", Nothing)
        Dim msnIMWindowClass As IntPtr = FindWindowEx(msnIMWindow, IntPtr.Zero, "IM Window Class", Nothing)
        Dim msnIMDirectUI As IntPtr = FindWindowEx(msnIMWindowClass, IntPtr.Zero, "DirectUIHWND", Nothing)
        Dim IID_IAccessible As New Guid("{618736E0-3C3D-11CF-810C-00AA00389B71}")
        If msnIMDirectUI.ToInt32 <> 0 Then
            If AccessibleObjectFromWindow(msnIMDirectUI, 0, IID_IAccessible, acc) = 0 Then
                acc = DirectCast(acc, Accessibility.IAccessible)
                For i As Integer = 1 To acc.accChildCount
                    Try
                        If acc.accChild(i) IsNot Nothing Then
                            acc2 = DirectCast(acc.accChild(i), Accessibility.IAccessible)
                            accMsnName = acc2.accName(0)
                            If accMsnName.ToLower.Equals("input") Then
                                accMsnValue = acc2.accValue(0)
                                MsgBox(accMsnValue) 'Ding
                                Exit For
                            End If
                        End If
                    Catch ex As Exception
                        'ignore COM exceptions
                    Finally
                        If acc2 IsNot Nothing Then
                            Marshal.ReleaseComObject(acc2)
                        End If
                    End Try
                Next i
                Marshal.FinalReleaseComObject(acc)
            End If
        Else
            Debug.Print("MSN IM Window doesn't exist on screen")
        End If
    End Sub

End Class

Open in new window

0
 
LVL 12

Author Closing Comment

by:Mohamed Abowarda
ID: 33608038
Great work!

Thanks,
0
 
LVL 29

Expert Comment

by:nffvrxqgrcfqvvc
ID: 33608041
BTW: Simply change line number 41 to "history" instead of "input" if you want the conversation(history) window.
0
 
LVL 12

Author Comment

by:Mohamed Abowarda
ID: 33608221
@egl1044: I realized that while testing the code.

Thanks,
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Parsing a CSV file is a task that we are confronted with regularly, and although there are a vast number of means to do this, as a newbie, the field can be confusing and the tools can seem complex. A simple solution to parsing a customized CSV fi…
If you need to start windows update installation remotely or as a scheduled task you will find this very helpful.
Michael from AdRem Software explains how to view the most utilized and worst performing nodes in your network, by accessing the Top Charts view in NetCrunch network monitor (https://www.adremsoft.com/). Top Charts is a view in which you can set seve…
In this brief tutorial Pawel from AdRem Software explains how you can quickly find out which services are running on your network, or what are the IP addresses of servers responsible for each service. Software used is freeware NetCrunch Tools (https…

724 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question