读取控制台缓冲区/输出 C++
Posted
技术标签:
【中文标题】读取控制台缓冲区/输出 C++【英文标题】:Reading Console Buffer / Output C++ 【发布时间】:2013-10-18 09:29:59 【问题描述】:我的问题很简单,但我似乎绝对找不到解决方案。
我有一个专用的游戏服务器 (JEDI ACADEMY JAMPDED),它是一个控制台应用程序。它不断写入一些信息,我想以某种方式处理数据。如果我能用 external 读取它的输出就很容易了。
问题:它不写入标准输出,所以不能用批处理文件传输,popen 也不起作用。
所以我想使用 WINAPI。我能够创建进程,但仍然无法读取输出。
我试过这些:
How do I call ::CreateProcess in c++ to launch a Windows executable?
CreateProcess and CreatePipe to execute a process and return output as a string in VC++
还有 MSDN 官方示例,但仍然没有。
这是 jampded.exe:
我的朋友从 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
也许这对我和其他人也有帮助:)
【问题讨论】:
如果它没有写入标准输出并且你没有源代码那么你就完成了,你无法修复它。 如果它不写入标准输出,那么它写入标准错误,可以使用command 2> file
重定向。话又说回来,另一个问题***.com/q/17064302/393701 表明 jampded 实际上可能会从控制台中分离出来......
不,它也不写入标准错误。
您可以使用ReadConsoleOutput
和朋友阅读控制台窗口的内容,但根据输出的多少,这可能不实用。
对于以某种方式编写程序的开发人员来说,地狱中有一个特殊的地方,它需要高级巫术将调试输出哄骗到另一个程序中。 Iburidu,感谢您分享您的代码。 jampded
的开发者们,你们的专属位置已经预留好了。
【参考方案1】:
Hans Passant 是对的。它不写入标准输出,但我可以用汇编修复它。所以他在这方面是不对的。
在此之后输出不同步,但可以通过将跳转交换为 nops 来成功修复它。更多:***.com/questions/23811572/writefile-function-with-assembly-debugging-syncing
所以总结一下:
它不仅适用于绝地学院专用服务器,它还可用于存储输出的任何二进制文件,但不适用于 STDOUT。
将 WriteFile 函数更改为写入 STDOUT(-11 为标准输出):
修复同步问题:
它适用于 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。或者你想要的任何东西。 :)
【讨论】:
以上是关于读取控制台缓冲区/输出 C++的主要内容,如果未能解决你的问题,请参考以下文章