Link to home
Start Free TrialLog in
Avatar of _ColdFire_
_ColdFire_Flag for United Kingdom of Great Britain and Northern Ireland

asked on

Read/Write textbox of another application

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 .
Avatar of mankowitz
mankowitz
Flag of United States of America image

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
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

*Oh...to go the opposite direction use WM_SETTEXT.
Avatar of _ColdFire_

ASKER

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
register new account - is free.
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...  =\
I need to get a text from the textbox where System messages are displayed.
IMG.png
Class name is RichEdit20W
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
Could u please download and check it for me.. cuz I really don't want to mess something up.
This is what I get...
RichEdit20W.png
That textbox is far away from main window as I see..
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:
https://www.experts-exchange.com/questions/23357525/get-all-Window-Handles-hWND-associated-with-a-Process.html
I have no clue how to use it...
I'll see if I can post a clean example of using it later today...   =)
(sorry...busy doing housework this morning!)
I compiled that program and used streamwriter so it writes output to text file and what i have is....
output.txt
new output file without personal information...
output.txt
how can i remove old one ?: D
ASKER CERTIFIED SOLUTION
Avatar of Mike Tomlinson
Mike Tomlinson
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
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?!
You'd have to show me some examples of what happens when people join, etc. so I could help you parse the data...
just a sec. :)
[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
So it shows in my application like that

[23:06:21] [System Message] <[Crack]>[Ping:219]  has joined your game!. Port: 57341
Program reads everything that is in textbox of garena but how can I write something into it?
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

code works fine but it clears all chat window before it posts my message, is there any way to fix that?
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.
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
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
time when each player joins or leaves
What's about EM_EXSETSEL and EMSETEXTEX , I don't really know how to use it.. can u give some examples please?
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:
https://www.experts-exchange.com/questions/25007794/Read-Write-textbox-of-another-application.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...
agree