[英]How to capture display output from a command prompt in Windows at any moment?
我打算捕获特定时间在命令提示符(cmd窗口)中显示的信息,并将其发送到文本文件。
我有一个C / C ++应用程序,该应用程序由如下的批处理脚本启动:
c:\myProgramInC.exe
echo "Ending with error"
PAUSE
myProgramInC.exe始终处于运行状态(无限循环),因此如果我的脚本进入echo命令,则意味着我的应用程序以异常结束结束。
我想要得到的是脚本最终执行之前的前几行,因为myProgramInC.exe总是打印有关正在发生的事情的信息,这对于查看发生错误时发生的情况非常有用。 像这样
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(每个程序都存储在不同的位置),因此我得到的消息是“多个进程匹配指定的名称。” 而其余选项对我来说却无济于事,因为我的应用不会停止响应,只是结束了。
有任何想法吗?
一个快速的技巧是在for /f
上下文中执行,您甚至不需要一个批处理文件,您可以直接从cmd行执行:
for /f "tokens=*" %F in ('c:\\myProgramInC.exe') do @echo %F >>myPrograminC.log
这将抑制所有输出,直到您的程序异常终止,然后才将所有消息写入文件。 如果您的应用很少写日志消息(或迅速失败:-),它应该可以工作。 我用1万行进行了测试。
下面的批处理代码基于相同的想法-请注意,即使只写最后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,1) do call echo %%line_%%C%%
您可以使用ReadConsoleOutputCharacter函数在C语言中轻松完成此操作。
好的,也许有一种更优雅的方法可以做到这一点,但前提是您拥有PowerShell。
创建一个名为Get-ConsoleAsText.ps1
的PowerShell脚本文件,其中包含以下脚本。 注意 ,我没有创建此脚本。 我在Windows PowerShell Blog-Capture控制台屏幕上找到了它。
#################################################################################################################
# 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:temp\ConsoleBuffer.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, 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:\Scripts\Get-ConsoleAsText.ps1"
您也可以像这样调用它以将内容捕获到文件中:
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
如果要处理它并在批处理文件中执行某些操作,则可以调用它并使用FOR
命令处理输出。 我将把这项工作留给您。
因此,例如,批处理文件如下所示,以将控制台输出捕获到文件中:
c:\myProgramInC.exe
echo "Ending with error"
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
PAUSE
最后,这就是我要使其工作的结果。 遵循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;
}
我在互联网上找到的大部分代码现在都没有URL(除了来自另一个论坛站点,而且我不知道是否可以引用竞争对手的站点),但是在google中进行一次搜索就不会很难找到它。
我添加了它写入文件和内存分配的部分。 它在VS C ++ 6中完美运行。
这对我来说很好,尽管可能更好。 两件事不是很好
如果有任何错误消息要报告回命令输出流,则可以通过用于STDOUT(标准输出)和STDERR(标准错误)的重定向操作符轻松地将其重定向。 根据您是否要捕获输出和/或错误,由您决定。 您很有可能正在寻找类似的东西:
“ 2”是重定向运算符的一部分,表示STDERR将被重定向并附加到文件名。
来源,示例和文档:
立即想到的一件事是将命令行输出重定向到文件:
c:\myProgramInC.exe >> myProgramInC.log
然后您可以查看日志文件中的内容。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.