[英]Win32 ReadFile Output without waiting for buffer
我使用CreateProcess()
對cmd.exe運行命令。 該命令本身具有無窮無盡的輸出,因此我使用了根據該答案修改的函數,以將部分輸出轉換為字符串。
#define BUFSIZE 4096
HANDLE g_hChildStd_OUT_Rd = NULL;
std::string ReadFromPipe(PROCESS_INFORMATION piProcInfo) {
DWORD dwRead;
CHAR chBuf[BUFSIZE];
ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
std::string s(chBuf, dwRead);
return s;
}
但是這段代碼會帶來一些問題。
首先,每次調用它時,它都可能在等待輸出緩沖到4096字節時凍結程序。
其次,它將始終僅在輸出隊列中獲得下一個4096字節。 (即使當前輸出大很多)
我想要的是調用該函數並獲取同時輸出的所有數據,並且還能夠設置要獲取的最小字節數(而不是緩沖區)。 如果最小字節數尚不可用,我希望它完全跳過ReadFile()
並只返回false
。 (而不是凍結應用程序)
這可能嗎?
Arkadiy的評論將我引向正確的方向。 我在PeekNamedPipe()
的幫助下使其工作
我當前的代碼:
#include <string>
#include <iostream>
#include <windows.h>
#include <stdio.h>
#pragma warning( disable : 4800 ) // hide bool warning
#define BUFSIZE 1024
HANDLE g_hChildStd_OUT_Rd = NULL;
std::string ReadFromPipe(PROCESS_INFORMATION piProcInfo) {
CHAR chBuf[BUFSIZE];
DWORD dwRead;
DWORD avail;
bool bSuccess = FALSE;
bool tSuccess = FALSE;
std::string out = "";
tSuccess = PeekNamedPipe( g_hChildStd_OUT_Rd, NULL, 0, NULL, &avail, NULL );
if (tSuccess && avail >= BUFSIZE) {
while (avail >= BUFSIZE) {
bSuccess=ReadFile( g_hChildStd_OUT_Rd, chBuf, BUFSIZE, &dwRead, NULL);
if( ! bSuccess || dwRead == 0 ) break;
std::string s(chBuf, dwRead);
out += s;
avail = avail - BUFSIZE;
}
return out;
} else {
return "[false]";
}
}
此函數在被調用時將返回自上次調用以來的輸出。 BUFSIZE
現在充當最小緩沖區,如果輸出小於最小緩沖區,則該函數將返回[false]
(作為字符串,不是bool)。
一種選擇是將從管道中讀取的代碼放在自己的線程中,並使其在循環中運行。 這樣可以防止主線程阻塞,並且您始終可以讀取盡可能多的數據。 挑戰在於,您現在需要一種獲取讀取線程的方法,以將數據傳輸回主線程。
另一種選擇是使用重疊的I / O,這在MSDN的ReadFile和CreateFile文檔中進行了討論。 無論何時從管道中讀取數據,這都是一種使操作系統回調的方式。 因此,您的ReadFile不會被阻止,但是(可能)在緩沖區中不會有任何數據,直到稍后。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.