Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
981 views
in Technique[技术] by (71.8m points)

windows - Reading Console Buffer / Output C++

My question is quite simple, but the solution seems absolutely impossible for me to find.

I have a dedicated game server (JEDI ACADEMY JAMPDED), which is a console application. It writes some information continously and I want to handle the data somehow. It would be easy if I could read the output of it with external.

Problem: It does not write to Standard Output, so can't be piped with batch file and popen does not work also.

So I wanted to do with WINAPI. I was able to create the process, but still can't read the output.

I tried these:

This is the jampded.exe: console

I got a visual-basic code from my friend, who reads ConsoleInput from Ingame, so I'm pretty sure, that it is possible to read the console:

SNIPPET:

Global hWnd = FindWindow_(#Null,"Jedi Knight Academy MP Console")              ;console window
Global hWnd2 = FindWindow_(#Null,"Jedi Knight?: Jedi Academy (MP)")            ;actual game window
Global inputhWnd = FindWindowEx_(hwnd,0,"edit",0)                                         ;the one to send stuff to
Global consolehWnd = FindWindowEx_(hwnd,inputhWnd,"edit",0)                      ;the one to read the console from


Procedure checkConsole()
    Protected wholetext.s, oldtext.s,text.s, checkname.s
    Repeat   
        wholetext = getText()
        If wholetext
            text = StringField(wholetext,CountString(wholetext,#CRLF$),#CRLF$)
            If oldtext <> text
                oldtext = text
                analyseConsole(@text)
            EndIf
        EndIf
        Delay(20)
        writePreferences()
    Until quit
EndProcedure

Procedure.s getText()
    Protected wholetext.s
    If hWnd And hWnd2
        If Not inputhWnd Or Not consolehWnd
            inputhWnd = FindWindowEx_(hWnd,0,"edit",0)
            consolehWnd =  FindWindowEx_(hWnd,inputhWnd,"edit",0)
        EndIf
        length = SendMessage_(consolehWnd, #WM_GETTEXTLENGTH, 0, 0)
        wholetext = Space(length)
        SendMessage_(consolehWnd,#WM_GETTEXT,length + SizeOf(Character),@wholetext)
        ProcedureReturn wholetext
    Else 
    If FindWindow_(#Null,"Jedi Knight Academy MP Console")
        hWnd = FindWindow_(#Null,"Jedi Knight Academy MP Console")
        hWnd2 = FindWindow_(#Null,"Jedi Knight?: Jedi Academy (MP)")
        inputhWnd = FindWindowEx_(hwnd,0,"edit",0)
        consolehWnd = FindWindowEx_(hwnd,inputhWnd,"edit",0)
    EndIf
    ProcedureReturn ""
    EndIf
    If @wholetext > 0
        FreeMemory(@wholetext)
    EndIf
EndProcedure

Maybe this could help me and others too :)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Hans Passant was right. It does not write to stdout, but I could fix it with assembly. So he was not right in that.

After this the output was unsynced, but it could be successfully fixed with exchanging a jump to nops. More: stackoverflow.com/questions/23811572/writefile-function-with-assembly-debugging-syncing

So sum everything up:

It is not just for Jedi Academy Dedicated Server, it can be useful for any binary file that stores output, but not to STDOUT.

Changing WriteFile function to write to STDOUT (-11 is stdout):

enter image description here

Fix syncing problem:

enter image description here

It is for JampDed 1.00, so if you want to use it for another version of JK, or for another game, you must find these addresses yourself. Best practise (in my opinion) if you go call by call deeper in the code. You may start from any message you find, then go deeper.

I have logged the whole debugging process this way:

004429a7 is (call 0043d440)
- 0043d44e (call 00422720)
-- 004227dD (call edx) - 2008F1B0
--- 2008f103 (call 2008cad0)
---- 2008c4d0
----- 2008c569 (call 2008b030)
------ 200a25f7 DWORD PTR DS:[20106A28] - 00422540
------- 0042254b (CALL DWORD PTR DS:[ECX+4]) - 0043d590
-------- 0043d8aa (call 0040fb40)
--------- 0040FC39 (call 0044b7a0)
---------- 0044b66c (call 004964dd)
----------- 00496500 (call 0049a4ba)
------------ 0049a4cd (call 00497d66)
------------- 00497d92 (call 0049e18c)
-------------- 0049e26f (CALL DWORD PTR DS:[4A715C])

And if you notice the last one is where WriteFile is located. And 2 before that is where the logsync stuff is located

So now

jampDed.exe | stdout.exe

works, and you can start creating your own mod for the server easily. Or anything you want. :)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...