读取控制台缓冲区/输出C ++

时间:2013-10-10 14:40:22

标签: c++ windows winapi game-development

我的问题很简单,但解决方案似乎绝对不可能找到。

我有一个专用游戏服务器(JEDI ACADEMY JAMPDED),这是一个控制台应用程序。它不断地写一些信息,我想以某种方式处理数据。如果我能用外部读取它的输出就很容易。

问题:它没有写入标准输出,因此无法使用批处理文件进行管道传输,而且popen也不起作用。

所以我想用WINAPI做。我能够创建进程,但仍然无法读取输出。

我试过这些:

这是jampded.exe: console

我从我的朋友那里得到了一个可视化基本代码,他从Ingame读取ConsoleInput,所以我很确定,可以读取控制台:

片段:

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

也许这对我和其他人也有帮助:)。

1 个答案:

答案 0 :(得分:1)

汉斯帕斯特是对的。它不会写入stdout,但我可以使用程序集修复它。所以他不对。

此后输出未同步,但可以通过交换跳转到nops成功修复。更多:stackoverflow.com/questions/23811572/writefile-function-with-assembly-debugging-syncing

所以总结一切:

它不仅适用于Jedi Academy Dedicated Server,它对于存储输出的任何二进制文件都很有用,但对STDOUT则无用。

更改WriteFile函数以写入STDOUT(-11是stdout):

enter image description here

修复同步问题:

enter image description here

适用于JampDed 1.00,因此如果您想将其用于其他版本的JK或其他游戏,您必须自己查找这些地址。最佳实践(在我看来)如果你在代码中更深入地打电话。您可以从找到的任何消息开始,然后再深入。

我已经用这种方式记录了整个调试过程:

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

如果您注意到最后一个是WriteFile所在的位置。之前的2是logsync东西所在的位置

所以现在

jampDed.exe | stdout.exe

有效,您可以轻松开始为服务器创建自己的mod。或任何你想要的。 :)