我打算在特定时刻捕获在命令提示符(cmd窗口)中显示的信息并将其发送到文本文件。
我在C / C ++中有一个应用程序,它是由像这样的批处理脚本启动的:
c:myProgramInC.exe echo "Ending with error" PAUSE
myProgramInC.exe总是运行(无限循环),所以如果我的脚本到达echo命令,这意味着我的应用程序以asynchronous结束。
我想要得到的是脚本的结束执行之前的前面的行,因为我的myProgramInC.exe总是打印有关正在发生的事情的信息,这将是非常有用的,看看发生错误时发生了什么。 像这样的东西
Bash输出发生在提示符之后,而不是之前,这意味着我必须手动按回车
c:myProgramInC.exe **** Execution of process to get te prevIoUs N lines in the command prompt **** echo "Ending with error" PAUSE
我知道CMD窗口有一个缓冲区,我一直在想从这样的缓冲区捕获所有这些数据。 以任何方式将这些信息作为文本存储在文件中?
我一直在尝试一些更专业的事情,以便与ProcDump的内存转储,但由于我有各种myProgramInC.exe同时运行(每一个存储在不同的位置)我只是得到消息“多进程匹配指定的名称“。 而其余的选项对我来说没有用,因为我的应用程序没有响应,它只是结束。
有任何想法吗?
如何在服务启动时查看日志文件?
当启动提示符时重新启动资源pipe理器作为pipe理员在Windows 8不起作用
改变〜/ .mc / ini不生效
您可以使用ReadConsoleOutputCharacter函数轻松地在C中执行此操作。
快速的技巧是在for /f执行,你甚至不需要批处理文件,你可以直接从cmd行执行:
for /f "tokens=*" %F in ('c:myProgramInC.exe') do @echo %F >>myPrograminC.log
这将抑制所有的输出,直到你的程序异常结束,只有这样才能将所有的消息写入文件。 如果您的应用程序很少写入日志消息(或快速失败:-)),它应该可以正常工作。 我用10000行测试了它。
下面的批处理代码是基于相同的想法 – 请注意,即使它只写了5最后一行, 它仍然必须扫描通过所有这些,所以我不知道它比上述1班轮好。
@echo off setlocal for /f "tokens=*" %%P in ('c:myProgramInC.exe') do ( for /L %%C in (4,-1,1) do ( set /A next=%%C+1 call set line_%%next%%=%%line_%%C%% ) set line_1=%%P ) echo program ended abnormally! %date% %time% for /L %%C in (5,1) do call echo %%line_%%C%%
最后,这是我得到它的工作。 在Harry Johnston的建议下,我搜索了ReadConsoleOutputCharacter函数的工作方式,并且运行了下一个程序。
#include "stdafx.h" #include <iostream> #include <windows.h> #include <fstream> #define BUFFER_SIZE 50000 int main(){ HANDLE hOut; COORD location = {0,0}; char *buffer=NULL; DWORD numberRead; std::ofstream fileLog; buffer = new TCHAR[BUFFER_SIZE]; if ( buffer==NULL ) { printf("nError: memory Could not be allocated.n"); return 1; } fileLog.open ("logger.txt"); if ( fileLog.fail() ) { printf("nError: file Could not be opened.n"); return 1; } hOut = GetStdHandle(STD_OUTPUT_HANDLE); ReadConsoleOutputCharacter(hOut,buffer,BUFFER_SIZE,location,&numberRead); fileLog << buffer ; free(buffer); fileLog.close(); return 0; }
我在互联网上找到的大部分代码,现在我没有网址(除了来自另一个论坛网站,我不知道是否可以引用竞争对手的网站),但在谷歌一个搜索不难找到它。
我添加了写入文件和分配内存的部分。 它在VS C ++ 6中完美运行。
这对我来说很好,虽然可能会更好。 两件事情不是很好
它将缓冲区中的所有内容写入文件,但不保留换行符,因此我得到一个文本文件,其中包含所有信息。
无法定义要捕获多少行。 它只需要从缓冲区的开头到程序开始的地方,但这并不坏,但是由于这个应用程序应该运行在不同的服务器上,每个服务器对于每一组命令提示符窗口都有不同的缓冲区,效率并不高只是在某些情况下使用50000字节的缓冲区时,缓冲区较小。 我认为这可能很多,但是由于它是实时分配的,使用尽可能多的内存也许并不是错误的。
好吧,可能有一个更好的方法来做到这一点,但这将工作假设你有PowerShell。
创建一个名为Get-ConsoleAsText.ps1的PowerShell脚本文件,其中包含以下脚本。 请注意 ,我没有创建这个脚本。 我在Windows PowerShell博客 – 捕获控制台屏幕上找到它。
################################################################################################################# # Get-ConsoleAsText.ps1 # # The script captures console screen buffer up to the current cursor position and returns it in plain text format. # # Returns: ASCII-encoded string. # # Example: # # $textFileName = "$env:tempConsoleBuffer.txt" # .Get-ConsoleAsText | out-file $textFileName -encoding ascii # $null = [System.Diagnostics.Process]::Start("$textFileName") # # Check the host name and exit if the host is not the Windows PowerShell console host. if ($host.Name -ne 'ConsoleHost') { write-host -ForegroundColor Red "This script runs only in the console host. You cannot run this script in $($host.Name)." exit -1 } # Initialize string builder. $textBuilder = new-object system.text.stringbuilder # Grab the console screen buffer contents using the Host console API. $bufferWidth = $host.ui.rawui.BufferSize.Width $bufferHeight = $host.ui.rawui.CursorPosition.Y $rec = new-object System.Management.Automation.Host.Rectangle 0,($bufferWidth),$bufferHeight $buffer = $host.ui.rawui.GetBufferContents($rec) # Iterate through the lines in the console buffer. for($i = 0; $i -lt $bufferHeight; $i++) { for($j = 0; $j -lt $bufferWidth; $j++) { $cell = $buffer[$i,$j] $null = $textBuilder.Append($cell.Character) } $null = $textBuilder.Append("`r`n") } return $textBuilder.ToString()
如果您自己调用PowerShell脚本,它将读取控制台缓冲区并将其写回到屏幕
PowerShell -noprofile -sta -command "C:ScriptsGet-ConsoleAsText.ps1"
PowerShell -noprofile -sta -command "C:ScriptsGet-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
如果要处理它并在批处理文件中执行一些操作,可以调用它并使用FOR命令处理输出。 我将把这个练习留给你。
所以,例如,你的批处理文件看起来像这样捕获控制台输出到一个文件:
c:myProgramInC.exe echo "Ending with error" PowerShell -noprofile -sta -command "C:ScriptsGet-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii" PAUSE
c:myProgramInC.exe >> myProgramInC.log
那么你可以看到什么是日志文件。
如果任何错误消息将被报告回命令输出流,则可以通过重定向操作符(STDOUT)(标准输出)和STDERR(标准错误)轻松地重定向它。 取决于你是否要捕捉输出和/或错误,取决于你。 更可能的是,你正在寻找像这样的东西:
命令2 >>文件名
“2”是重定向操作符的一部分,表示STDERR将被重定向并附加到文件名。
来源,例子和文件:
http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/redirection.mspx
http://ss64.com/nt/Syntax-redirection.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 [email protected] 举报,一经查实,本站将立刻删除。