程序很简单:
程序A:
#include "stdio.h"
int main()
{
int index = 0;
        int i = 0;
for (i = 1; i <9988998; i++) {
printf("Current Count is %d\n", index++);Sleep(10 * 999);
}
}通过管道获取stdout时会卡死,究其原因,是因为windows的stdout输出是全缓冲的,只有缓冲区满了才会输出,但我要实现的有一行就输出一行,在命令行下可以这样,但用管道一直实现不了,在网上搜了很多代码,虽然说是异步获取,但也必须在缓冲区满了后才能输出,现在的问题是程序A我无法修改,上面只是个例子,实际功能比它复杂很多,但原理一样,也没办法把windows的命令行改为行缓冲,各位高手有什么好办法?

解决方案 »

  1.   

    输出换行符,或者fflush 函数强制刷出可以吧?
      

  2.   

    使用PeekNamedPipe查询管道内的数据,有则读取,没有则不读。主要是防止ReadFile堵塞。
      

  3.   


    应该可以实现,类似 后门绑定cmd反弹那种。控制台的输入输出都接管了。
      

  4.   

    仅供参考:#pragma comment(lib,"user32")
    #include <stdio.h>
    #include <string.h>
    #include <windows.h>
    int main() {
        SECURITY_ATTRIBUTES sa          = {0};
        STARTUPINFO         si          = {0};
        PROCESS_INFORMATION pi          = {0};
        HANDLE              hPipeOutputRead  = NULL;
        HANDLE              hPipeOutputWrite = NULL;
        HANDLE              hPipeInputRead   = NULL;
        HANDLE              hPipeInputWrite  = NULL;
        BOOL                bTest = 0;
        DWORD               dwNumberOfBytesRead = 0;
        DWORD               dwNumberOfBytesWrite = 0;
        CHAR                szMsg[100];
        CHAR                szBuffer[256];    sa.nLength = sizeof(sa);
        sa.bInheritHandle = TRUE;
        sa.lpSecurityDescriptor = NULL;    // Create pipe for standard output redirection.
        CreatePipe(&hPipeOutputRead,  // read handle
                &hPipeOutputWrite, // write handle
                &sa,      // security attributes
                0      // number of bytes reserved for pipe - 0 default
                );    // Create pipe for standard input redirection.
        CreatePipe(&hPipeInputRead,  // read handle
                &hPipeInputWrite, // write handle
                &sa,      // security attributes
                0      // number of bytes reserved for pipe - 0 default
                );    // Make child process use hPipeOutputWrite as standard out,
        // and make sure it does not show on screen.
        si.cb = sizeof(si);
        si.dwFlags     = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
        si.wShowWindow = SW_HIDE;
        si.hStdInput   = hPipeInputRead;
        si.hStdOutput  = hPipeOutputWrite;
        si.hStdError   = hPipeOutputWrite;    CreateProcess (
              NULL, "cmd.exe",
              NULL, NULL,
              TRUE, 0,
              NULL, NULL,
              &si, &pi);    // Now that handles have been inherited, close it to be safe.
        // You don't want to read or write to them accidentally.
        CloseHandle(hPipeOutputWrite);
        CloseHandle(hPipeInputRead);    // Now test to capture DOS application output by reading
        // hPipeOutputRead.  Could also write to DOS application
        // standard input by writing to hPipeInputWrite.
        sprintf(szMsg, "ver\n");
        WriteFile(
              hPipeInputWrite,      // handle of the write end of our pipe
              &szMsg,               // address of buffer that send data
              strlen(szMsg),        // number of bytes to write
              &dwNumberOfBytesWrite,// address of number of bytes read
              NULL                  // non-overlapped.
              );    while(TRUE)
        {
           bTest=ReadFile(
              hPipeOutputRead,      // handle of the read end of our pipe
              &szBuffer,            // address of buffer that receives data
              256,                  // number of bytes to read
              &dwNumberOfBytesRead, // address of number of bytes read
              NULL                  // non-overlapped.
              );      if (!bTest){
              sprintf(szMsg, "Error #%d reading pipe.",GetLastError());
              printf("%s",szMsg);
              break;
          }      // do something with data.
          szBuffer[dwNumberOfBytesRead] = 0;  // null terminate
          printf("%s",szBuffer);
          if ('>'==szBuffer[dwNumberOfBytesRead-1]) break;
        }    sprintf(szMsg, "chcp\nexit\n");
        WriteFile(
              hPipeInputWrite,      // handle of the write end of our pipe
              &szMsg,               // address of buffer that send data
              strlen(szMsg),        // number of bytes to write
              &dwNumberOfBytesWrite,// address of number of bytes read
              NULL                  // non-overlapped.
              );    while(TRUE)
        {
           bTest=ReadFile(
              hPipeOutputRead,      // handle of the read end of our pipe
              &szBuffer,            // address of buffer that receives data
              256,                  // number of bytes to read
              &dwNumberOfBytesRead, // address of number of bytes read
              NULL                  // non-overlapped.
              );      if (!bTest){
              sprintf(szMsg, "Error #%d reading pipe.",GetLastError());
              printf("%s",szMsg);
              break;
          }      // do something with data.
          szBuffer[dwNumberOfBytesRead] = 0;  // null terminate
          printf("%s",szBuffer);
        }    // Wait for CONSPAWN to finish.
        WaitForSingleObject (pi.hProcess, INFINITE);    // Close all remaining handles
        CloseHandle (pi.hProcess);
        CloseHandle (hPipeOutputRead);
        CloseHandle (hPipeInputWrite);    return 0;
    }
    //C:\test>test
    //Microsoft Windows [版本 5.2.3790]
    //(C) 版权所有 1985-2003 Microsoft Corp.
    //
    //C:\test>ver
    //
    //Microsoft Windows [版本 5.2.3790]
    //
    //C:\test>chcp
    //活动的代码页: 936
    //
    //C:\test>exit
    //Error #109 reading pipe.
    //C:\test>
      

  5.   

    今天遇到同样的问题,找遍了,没有在网上发现解决方案,抱着试试看的想法,终于找到了最好的解决方案。
    无须命名管道,只需在读取前加上GetFileSizeEx判断即可,代码如下:
    char buf[ 1024 ];
    LARGE_INTEGER off;
    ::GetFileSizeEx( z_stdoutRd, &off );
    if ( off.LowPart || off.HighPart )
    {
    DWORD readSize = 0;
    BOOL b = ::ReadFile( z_stdoutRd, buf, 1024, &readSize, NULL );
    buf[ readSize ] = 0;
    ::OutputDebugStringA( buf );
    }