[Webinar] Learn how to a build a cloud-first strategyRegister Now

x
?
Solved

Read/Write textbox of another application

Posted on 2009-12-29
34
Medium Priority
?
2,835 Views
Last Modified: 2013-11-26
Hi, I would like to know how can I read/write a textbox of anothers application (process) textbox1.

Example:
My program is - something.exe and there is a textbox in it .
Button1 gets a text from something2.exe (textbox1)
Button2 write's a text to something2.exe (textbox1)

Note: I don't have a source code of something2.exe .
0
Comment
Question by:_ColdFire_
  • 22
  • 11
34 Comments
 
LVL 24

Expert Comment

by:mankowitz
ID: 26138271
I don't know how you could retreive a value from another program without decompiling it or looking through it with a debugger.

Sending information to another application should not be too hard, using sendkeys. Here is an example: http://msdn.microsoft.com/en-us/library/ms172702(VS.80).aspx
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26138324
In a nutshell, obtain a handle to the TextBox via APIs such as FindWindow()/FindWindowEx() then grab the text from it using SendMessage() and WM_GETTEXT.

Here is an example using NotePad:
Public Class Form1

    Private Const WM_GETTEXT As Integer = &HD
    Private Const WM_GETTEXTLENGTH As Integer = &HE

    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" _
            (ByVal hWnd1 As IntPtr, ByVal hWnd2 As IntPtr, ByVal lpsz1 As String, _
            ByVal lpsz2 As String) As Integer

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal hWnd As IntPtr, ByVal wMsg As Integer, _
        ByVal wParam As Integer, ByVal lParam As Integer) As Integer

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal hWnd As IntPtr, ByVal wMsg As Integer, _
        ByVal wParam As Integer, ByVal lParam As System.Text.StringBuilder) As Integer

    Private Function GetText(ByVal hWnd As IntPtr) As String
        Dim textLength As Integer = SendMessage(hWnd, WM_GETTEXTLENGTH, 0, 0) + 1
        Dim sb As New System.Text.StringBuilder(textLength)
        If textLength > 0 Then
            Call SendMessage(hWnd, WM_GETTEXT, textLength, sb)
        End If
        Return sb.ToString
    End Function

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim ps() As Process = Process.GetProcessesByName("notepad")
        If ps.Length > 0 Then
            Dim noteWnd As IntPtr = ps(0).MainWindowHandle
            Dim editWnd As Integer = FindWindowEx(noteWnd, IntPtr.Zero, "Edit", "")
            Dim sTemp As String = GetText(editWnd)
            MessageBox.Show(sTemp)
        End If
    End Sub

End Class

Open in new window

0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26138328
*Oh...to go the opposite direction use WM_SETTEXT.
0
Free Backup Tool for VMware and Hyper-V

Restore full virtual machine or individual guest files from 19 common file systems directly from the backup file. Schedule VM backups with PowerShell scripts. Set desired time, lean back and let the script to notify you via email upon completion.  

 

Author Comment

by:_ColdFire_
ID: 26138630
Idle_Mind , code works for notepad, but it doesn't work for the application i need.
Actually applications name is Garena.exe. I have to enter the room and there is chat window from witch i want to be able to read text and write.

If you don't know that program , then probably you can download it and register and then have a look at it. :P

http://download3.garena.com/Garena4.0Beta.rar
0
 

Author Comment

by:_ColdFire_
ID: 26138634
register new account - is free.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26138735
Can you post a screenshot of the window for us?

Use Spy++ or the free Winspector (Google it) to inspect the target app.  Drag the "cross hairs" over the target window and report back the classname of it.

If that is a JAVA app then you may have to resort to other lower level approaches...  =\
0
 

Author Comment

by:_ColdFire_
ID: 26138964
I need to get a text from the textbox where System messages are displayed.
IMG.png
0
 

Author Comment

by:_ColdFire_
ID: 26139016
Class name is RichEdit20W
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26139099
Ok...good start!

Do you have Spy++ (it comes with Visual Studio)?  If not, please download WinSpector and use it to find out some useful information about your target app.

I've attached a screenshot of Winspector after I've dragged the cross-hairs onto the edit portion.  This allows you to see the hierarchy of the controls with respect to each other.

This is necessary for us to determine the correct number and/or order of FindWindow()/FindWindowEx() calls to get a handle to your "RichEdit20W" window.

As you can see, in Notepad, the "Edit" window is a direct child of the main window which makes the code very easy.

Your app will probably be more complex and require more in-depth code to get the correct window:
WinspectorWithNotepad.jpg
0
 

Author Comment

by:_ColdFire_
ID: 26139330
Could u please download and check it for me.. cuz I really don't want to mess something up.
0
 

Author Comment

by:_ColdFire_
ID: 26139363
This is what I get...
RichEdit20W.png
0
 

Author Comment

by:_ColdFire_
ID: 26139541
That textbox is far away from main window as I see..
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26139593
Haha...it sure is buried deep in there!  Using FindWindow()/FindWindowEx() you have to start with the main window and then get the next parent in the sequence.  When you have multiple classes of the same type at the same level and you need the one that is NOT the first one then you have to call it multiple times to get the correct one.  Pain in the butt...

An alternative approach is to use the EnumWindows()/EnumChildWindows() approach to find the target window:
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Basic.NET/Q_23357525.html
0
 

Author Comment

by:_ColdFire_
ID: 26139637
I have no clue how to use it...
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26139685
I'll see if I can post a clean example of using it later today...   =)
(sorry...busy doing housework this morning!)
0
 

Author Comment

by:_ColdFire_
ID: 26139761
I compiled that program and used streamwriter so it writes output to text file and what i have is....
output.txt
0
 

Author Comment

by:_ColdFire_
ID: 26139821
new output file without personal information...
output.txt
0
 

Author Comment

by:_ColdFire_
ID: 26139823
how can i remove old one ?: D
0
 
LVL 86

Accepted Solution

by:
Mike Tomlinson earned 2000 total points
ID: 26141485
See if this works...
(I just copied Bob's code, pasted it below the form code, and added the necessary Imports at the top)
Imports System.Collections.Generic
Imports System.Runtime.InteropServices
Imports System.Text
Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim ps() As Process = Process.GetProcessesByName("garena")
        If ps.Length > 0 Then
            Dim enumerator As New WindowsEnumerator
            For Each child As ApiWindow In enumerator.GetChildWindows(ps(0).MainWindowHandle)
                If child.ClassName.ToLower = "richedit20w" Then
                    Dim txt As String = child.MainWindowTitle
                    MessageBox.Show(txt, "Is this the text?")
                    Exit For
                End If
            Next
        End If
    End Sub

End Class

Public Class ApiWindow
    Public MainWindowTitle As String = ""
    Public ClassName As String = ""
    Public hWnd As Int32
End Class

''' <summary> 
''' Enumerate top-level and child windows 
''' </summary> 
''' <example> 
''' Dim enumerator As New WindowsEnumerator()
''' For Each top As ApiWindow in enumerator.GetTopLevelWindows()
'''    Console.WriteLine(top.MainWindowTitle)
'''    For Each child As ApiWindow child in enumerator.GetChildWindows(top.hWnd) 
'''        Console.WriteLine(" " + child.MainWindowTitle)
'''    Next child
''' Next top
''' </example> 
Public Class WindowsEnumerator

    Private Delegate Function EnumCallBackDelegate(ByVal hwnd As Integer, ByVal lParam As Integer) As Integer

    ' Top-level windows.
    Private Declare Function EnumWindows Lib "user32" _
     (ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As Integer

    ' Child windows.
    Private Declare Function EnumChildWindows Lib "user32" _
     (ByVal hWndParent As Integer, ByVal lpEnumFunc As EnumCallBackDelegate, ByVal lParam As Integer) As Integer

    ' Get the window class.
    Private Declare Function GetClassName _
     Lib "user32" Alias "GetClassNameA" _
     (ByVal hwnd As Integer, ByVal lpClassName As StringBuilder, ByVal nMaxCount As Integer) As Integer

    ' Test if the window is visible--only get visible ones.
    Private Declare Function IsWindowVisible Lib "user32" _
     (ByVal hwnd As Integer) As Integer

    ' Test if the window's parent--only get the one's without parents.
    Private Declare Function GetParent Lib "user32" _
     (ByVal hwnd As Integer) As Integer

    ' Get window text length signature.
    Private Declare Function SendMessage _
     Lib "user32" Alias "SendMessageA" _
     (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As Int32) As Int32

    ' Get window text signature.
    Private Declare Function SendMessage _
     Lib "user32" Alias "SendMessageA" _
     (ByVal hwnd As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal lParam As StringBuilder) As Int32

    Private _listChildren As New List(Of ApiWindow)
    Private _listTopLevel As New List(Of ApiWindow)

    Private _topLevelClass As String = ""
    Private _childClass As String = ""

    ''' <summary>
    ''' Get all top-level window information
    ''' </summary>
    ''' <returns>List of window information objects</returns>
    Public Overloads Function GetTopLevelWindows() As List(Of ApiWindow)

        EnumWindows(AddressOf EnumWindowProc, &H0)

        Return _listTopLevel

    End Function

    Public Overloads Function GetTopLevelWindows(ByVal className As String) As List(Of ApiWindow)

        _topLevelClass = className

        Return Me.GetTopLevelWindows()

    End Function

    ''' <summary>
    ''' Get all child windows for the specific windows handle (hwnd).
    ''' </summary>
    ''' <returns>List of child windows for parent window</returns>
    Public Overloads Function GetChildWindows(ByVal hwnd As Int32) As List(Of ApiWindow)

        ' Clear the window list.
        _listChildren = New List(Of ApiWindow)

        ' Start the enumeration process.
        EnumChildWindows(hwnd, AddressOf EnumChildWindowProc, &H0)

        ' Return the children list when the process is completed.
        Return _listChildren

    End Function

    Public Overloads Function GetChildWindows(ByVal hwnd As Int32, ByVal childClass As String) As List(Of ApiWindow)

        ' Set the search
        _childClass = childClass

        Return Me.GetChildWindows(hwnd)

    End Function

    ''' <summary>
    ''' Callback function that does the work of enumerating top-level windows.
    ''' </summary>
    ''' <param name="hwnd">Discovered Window handle</param>
    ''' <returns>1=keep going, 0=stop</returns>
    Private Function EnumWindowProc(ByVal hwnd As Int32, ByVal lParam As Int32) As Int32

        ' Eliminate windows that are not top-level.
        If GetParent(hwnd) = 0 AndAlso CBool(IsWindowVisible(hwnd)) Then

            ' Get the window title / class name.
            Dim window As ApiWindow = GetWindowIdentification(hwnd)

            ' Match the class name if searching for a specific window class.
            If _topLevelClass.Length = 0 OrElse window.ClassName.ToLower() = _topLevelClass.ToLower() Then
                _listTopLevel.Add(window)
            End If

        End If

        ' To continue enumeration, return True (1), and to stop enumeration 
        ' return False (0).
        ' When 1 is returned, enumeration continues until there are no 
        ' more windows left.

        Return 1

    End Function

    ''' <summary>
    ''' Callback function that does the work of enumerating child windows.
    ''' </summary>
    ''' <param name="hwnd">Discovered Window handle</param>
    ''' <returns>1=keep going, 0=stop</returns>
    Private Function EnumChildWindowProc(ByVal hwnd As Int32, ByVal lParam As Int32) As Int32

        Dim window As ApiWindow = GetWindowIdentification(hwnd)

        ' Attempt to match the child class, if one was specified, otherwise
        ' enumerate all the child windows.
        If _childClass.Length = 0 OrElse window.ClassName.ToLower() = _childClass.ToLower() Then
            _listChildren.Add(window)
        End If

        Return 1

    End Function

    ''' <summary>
    ''' Build the ApiWindow object to hold information about the Window object.
    ''' </summary>
    Private Function GetWindowIdentification(ByVal hwnd As Integer) As ApiWindow

        Const WM_GETTEXT As Int32 = &HD
        Const WM_GETTEXTLENGTH As Int32 = &HE

        Dim window As New ApiWindow()

        Dim title As New StringBuilder()

        ' Get the size of the string required to hold the window title.
        Dim size As Int32 = SendMessage(hwnd, WM_GETTEXTLENGTH, 0, 0)

        ' If the return is 0, there is no title.
        If size > 0 Then
            title = New StringBuilder(size + 1)

            SendMessage(hwnd, WM_GETTEXT, title.Capacity, title)
        End If

        ' Get the class name for the window.
        Dim classBuilder As New StringBuilder(64)
        GetClassName(hwnd, classBuilder, 64)

        ' Set the properties for the ApiWindow object.
        window.ClassName = classBuilder.ToString()
        window.MainWindowTitle = title.ToString()
        window.hWnd = hwnd

        Return window

    End Function

End Class

Open in new window

0
 

Author Comment

by:_ColdFire_
ID: 26141898
It works, the thing is, that I have to get list of tcp connections and when player joins (Garena types message) Player joined your game. On tcp connections I can see that somebody connected like localhost:someport (localhost:46910) i have to determinate which connection for which player is .. as it just shows localhost and port but doesnt show players name.. so how can i capture that?!
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26141927
You'd have to show me some examples of what happens when people join, etc. so I could help you parse the data...
0
 

Author Comment

by:_ColdFire_
ID: 26141994
just a sec. :)
0
 

Author Comment

by:_ColdFire_
ID: 26142059
[23:06:21] [System Message] <[Crack]>[Ping:219]  has joined your game!.

So how can i filter only messages when somebody joined and then create a time stamp when NEW TCP Connection is created for the process on that time.

On the image you can see that somebody is connected to my game and there is local port 6112 which remains same for everyone but remote port is different for every player.

On the image there is port 57341 if there would be other player there would be other connection with different port like 57342 or 61836 .. any free random port. So i have to capture the time when player is connected and time when that TCP connection is established.
TCP.png
0
 

Author Comment

by:_ColdFire_
ID: 26142077
So it shows in my application like that

[23:06:21] [System Message] <[Crack]>[Ping:219]  has joined your game!. Port: 57341
0
 

Author Comment

by:_ColdFire_
ID: 26145350
Program reads everything that is in textbox of garena but how can I write something into it?
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26145740
I haven't looked at analyzing the strings yet...hopefully I can get to that later today.

As for writing something to the box, try the below out.

I added a second button and some additional code:
    Private Const WM_GETTEXTLENGTH As Integer = &HE
    Private Const EM_SETSEL As Integer = &HB1
    Private Const EM_REPLACESEL As Integer = &HC

    Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
        (ByVal hwnd As Int32, ByVal wMsg As Integer, ByVal wParam As Integer, _
        ByVal lParam As String) As Integer

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim ps() As Process = Process.GetProcessesByName("garena")
        If ps.Length > 0 Then
            Dim enumerator As New WindowsEnumerator
            For Each child As ApiWindow In enumerator.GetChildWindows(ps(0).MainWindowHandle)
                If child.ClassName.ToLower = "richedit20w" Then
                    Dim textLength As Integer = SendMessage(child.hWnd, WM_GETTEXTLENGTH, 0, 0)
                    SendMessage(child.hWnd, EM_SETSEL, textLength, 0) 
                    SendMessage(child.hWnd, EM_REPLACESEL, 0, "Can you hear me now?" & vbCrLf) 
                    Exit For
                End If
            Next
        End If
    End Sub

Open in new window

0
 

Author Comment

by:_ColdFire_
ID: 26145905
code works fine but it clears all chat window before it posts my message, is there any way to fix that?
0
 

Author Comment

by:_ColdFire_
ID: 26145956
well, it doesn't work like it should be cuz only I can see that message. Don't overload yourself as this function is not too essential for me... just get on with analyzing the strings when u can.
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26146013
That code works with a standard edit control (like in Notepad) and I wasn't too sure it would work with a RichEdit control.

There specific messages for a RichEdit you can use but they require a little more code...think you need EM_EXSETSEL and EMSETEXTEX:
http://msdn.microsoft.com/en-us/library/bb788007(VS.85).aspx
http://msdn.microsoft.com/en-us/library/bb774284(VS.85).aspx
0
 

Author Comment

by:_ColdFire_
ID: 26147055
Ok, application works fine, it reads text from garena and it's ok. So now i just need to filter those text messages and show only player join/leave messages and time like hh:mm:ss:miliseconds
0
 

Author Comment

by:_ColdFire_
ID: 26147060
time when each player joins or leaves
0
 

Author Comment

by:_ColdFire_
ID: 26158725
What's about EM_EXSETSEL and EMSETEXTEX , I don't really know how to use it.. can u give some examples please?
0
 
LVL 86

Expert Comment

by:Mike Tomlinson
ID: 26184535
I would consider your "core" question WELL answered:

    "I need to get a text from the textbox where System messages are displayed."

With this comment:
http://www.experts-exchange.com/Programming/Languages/.NET/Visual_Studio_.NET_2005/Q_25007794.html#26141485
And your response of:

    "It works"

I suggest you close this question and ask a new one for the parsing aspect as it really isn't related to the original problem...
0
 

Author Comment

by:_ColdFire_
ID: 26185493
agree
0

Featured Post

Veeam Disaster Recovery in Microsoft Azure

Veeam PN for Microsoft Azure is a FREE solution designed to simplify and automate the setup of a DR site in Microsoft Azure using lightweight software-defined networking. It reduces the complexity of VPN deployments and is designed for businesses of ALL sizes.

Question has a verified solution.

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

Recently while returning home from work my wife (another .NET developer) was murmuring something. On further poking she said that she has been assigned a task where she has to serialize and deserialize objects and she is afraid of serialization. Wha…
In my previous article (http://www.experts-exchange.com/Programming/Languages/.NET/.NET_Framework_3.x/A_4362-Serialization-in-NET-1.html) we saw the basics of serialization and how types/objects can be serialized to Binary format. In this blog we wi…
Are you ready to place your question in front of subject-matter experts for more timely responses? With the release of Priority Question, Premium Members, Team Accounts and Qualified Experts can now identify the emergent level of their issue, signal…
Despite its rising prevalence in the business world, "the cloud" is still misunderstood. Some companies still believe common misconceptions about lack of security in cloud solutions and many misuses of cloud storage options still occur every day. …
Suggested Courses

867 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