Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何随时从Windows中的命令提示符捕获显示输出?_Windows_Batch File_Cmd_Buffer_Prompt - Fatal编程技术网

如何随时从Windows中的命令提示符捕获显示输出?

如何随时从Windows中的命令提示符捕获显示输出?,windows,batch-file,cmd,buffer,prompt,Windows,Batch File,Cmd,Buffer,Prompt,我试图捕获特定时刻命令提示符(cmd窗口)中显示的de信息,并将其发送到文本文件 我有一个C/C++中的应用程序,由以下批处理脚本启动: c:\myProgramInC.exe echo "Ending with error" PAUSE myProgramInC.exe始终在运行(具有无限循环),因此如果我的脚本到达echo命令,则意味着我的应用程序以异常结束 我想得到的是脚本结束执行之前的前几行,因为myProgramInC.exe总是打印有关正在发生的事情的信息,如果能看到错误发生时发生

我试图捕获特定时刻命令提示符(cmd窗口)中显示的de信息,并将其发送到文本文件

我有一个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同时运行(每个都存储在不同的位置),所以我只得到消息“多个进程匹配指定的名称”其余的选项对我来说都没用,因为我的应用程序不会没有响应,它只是结束


有什么想法吗?

minde立即想到的一件事是将命令行的输出重定向到一个文件:

c:\myProgramInC.exe >> myProgramInC.log
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
c:\myProgramInC.exe
echo "Ending with error"
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
PAUSE

然后您可以查看日志文件中的内容。

您可以使用该函数在C中轻松完成此操作。

快速技巧是在
for/f
的上下文中执行,您甚至不需要批处理文件,您可以直接从cmd行执行:
for/f“令牌=*%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,1) do call echo %%line_%%C%% 

好的,可能有一种更优雅的方法来实现这一点,但如果您有PowerShell,这将起作用

创建一个名为
Get ConsoleAsText.ps1
的PowerShell脚本文件,其中包含以下脚本注意,我没有创建此脚本。我在家里找到的

如果您单独调用PowerShell脚本,它将读取控制台缓冲区并将其写回屏幕

PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1"
您也可以这样调用它以将内容捕获到文件:

c:\myProgramInC.exe >> myProgramInC.log
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
c:\myProgramInC.exe
echo "Ending with error"
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
PAUSE
如果要处理它并在批处理文件中执行某些操作,可以使用
FOR
命令调用它并处理输出。我将把这个练习留给你做

例如,您的批处理文件如下所示,以将控制台输出捕获到文件:

c:\myProgramInC.exe >> myProgramInC.log
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
c:\myProgramInC.exe
echo "Ending with error"
PowerShell -noprofile -sta -command "C:\Scripts\Get-ConsoleAsText.ps1 | Out-File MyOutput.txt -encoding ascii"
PAUSE

最后,这就是我所能做到的。听从哈里·约翰斯顿的建议 我搜索了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;
}
#包括“stdafx.h”
#包括
#包括
#包括
#定义缓冲区大小50000
int main(){
处理hOut;
坐标位置={0,0};
char*buffer=NULL;
德沃德数里德;
std::of流文件日志;
缓冲区=新的TCHAR[缓冲区大小];
if(buffer==NULL)
{
printf(“\n错误:无法分配内存。\n”);
返回1;
}
fileLog.open(“logger.txt”);
if(fileLog.fail())
{
printf(“\n错误:无法打开文件。\n”);
返回1;
}
hOut=GetStdHandle(标准输出句柄);
ReadConsoleOutputCharacter(小时、缓冲区、缓冲区大小、位置和编号READ);

fileLog如果要将任何错误消息报告回命令输出流,可以通过STDOUT(标准输出)和STDERR(标准错误)的重定向操作符轻松重定向。取决于您是否要捕获输出和/或错误,这取决于您自己。很可能,您正在寻找以下内容:

  • 命令2>>文件名
“2”是重定向操作符的一部分,表示STDERR将被重定向并附加到文件名

来源、示例和文档:


  • 感谢artpet,但这不是一个选项,因为我的应用程序一直都在磁盘上写,而且它是一个关键的时间响应程序,此外,还有很多这样的实例,让大约30个程序一直写到磁盘上会给服务器资源带来很大压力。这就是为什么它只有在必要时才应该写在磁盘上。Wh此时正是您需要捕获程序输出的时刻?是特定字符串还是某个超时?此外,procdump接受正在运行的程序的PId而不是名称。您可以使用windows任务管理器或Process Explorer工具从系统内部获取进程Id。我需要捕获应用程序打印的最后几行。它显示有关我可以做一些分析,试图找出问题所在。事实上,大多数情况下,这只是一个数组溢出的问题,但由于我的应用程序使用的是外部应用程序提供的信息,因此我很容易显示我的应用程序有异常终止,因为提供给它的信息错误。使用windows任务管理器r Process Explorer不是一个选项,因为它的想法是让批处理在结束时自动捕获数据;事实上,我在批处理脚本示例中使用的暂停将不存在,从而确保命令提示符关闭,并有第三个应用程序(像某种守护程序一样运行)将识别此项,并打开一个新的命令提示符,确保myProgramInC.exe始终运行,即使在发生错误后也是如此。我将查看此函数,也许它是最佳选项。我会让您知道这是否适用于我周一的工作。我喜欢第一个选项w