【发布时间】:2010-07-12 00:10:07
【问题描述】:
好的,我已经问了几个关于尝试完成我想做的事情的不同方面的问题。这次我只是从命名管道中读取数据时遇到了大问题。我想我已经获得了足够的信息来完成我正在做的项目,如果我能正确设置的话。我将在下面包含所有相关代码,但我的任务是:从我没有编写的程序中读取输出(连续)并将其发布到 WinAPI。所以我的问题是我刚刚从匿名管道切换到命名管道,并且在尝试正确设置它们以便检索信息时遇到了问题。我有一个基于 MSDN 示例的框架设置。
#define WAIT_TIME 2 // 2s
#define INSTANCES 4 // Number of threads
#define CONNECT_STATE 0
#define READ_STATE 1
#define WRITE_STATE 2
#define WORLDRD 0
#define WORLDWR 1
#define WORLDINRD 2
#define WORLDINWR 3
#define BUFSIZE 0x1000 // Buffer size 4096 (in bytes)
#define PIPE_TIMEOUT 0x1388 // Timeout 5000 (in ms)
void Arc_Redirect::createProcesses()
{
TCHAR programName[]=TEXT("EXEC_PROGRAM.exe");
PROCESS_INFORMATION pi;
STARTUPINFO si;
BOOL bSuccess = FALSE;
ZeroMemory(hEvents,(sizeof(hEvents)*INSTANCES));
ZeroMemory(outStd,(sizeof(PIPE_HANDLES)*INSTANCES));
// Prep pipes
for(int i=0;i<INSTANCES;i++)
{
hEvents[i] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if(hEvents[i] == NULL)
throw "Could not init program!";
outStd[i].o1.hEvent = hEvents[i];
outStd[i].hPipeInst = ::CreateNamedPipe(
TEXT("\\\\.\\pipe\\arcworld"), PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, BUFSIZE*sizeof(TCHAR), BUFSIZE*sizeof(TCHAR), PIPE_TIMEOUT, NULL);
if(outStd[i].hPipeInst == INVALID_HANDLE_VALUE)
throw "Could not init program!";
outStd[i].pendingIO = getState(outStd[i].hPipeInst,&outStd[i].o1);
outStd[i].dwState = outStd[i].pendingIO ?
CONNECT_STATE : READ_STATE;
}
// Set stuff up
ZeroMemory( &pi, sizeof(PROCESS_INFORMATION));
ZeroMemory( &si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.hStdError = outStd[WORLDRD].hPipeInst;
si.hStdOutput = outStd[WORLDRD].hPipeInst;
si.hStdInput = outStd[WORLDINWR].hPipeInst;
si.dwFlags |= STARTF_USESHOWWINDOW|STARTF_USESTDHANDLES|FILE_FLAG_OVERLAPPED;
// Start our process with the si info
CreateProcess(programName,NULL,NULL,NULL,FALSE,0,NULL,NULL,&si,&pi);
}
BOOL Arc_Redirect::getState(HANDLE hPipe, LPOVERLAPPED lpo)
{
BOOL connected, pendingIO = FALSE;
// Overlap connection for this pipe
connected = ::ConnectNamedPipe(hPipe,lpo);
if(connected)
throw "ConnectNamedPipe(); failed!";
switch(GetLastError())
{
case ERROR_IO_PENDING:
pendingIO = TRUE;
break;
case ERROR_PIPE_CONNECTED:
if(SetEvent(lpo->hEvent))
break;
default:
throw "ConnectNamedPipe(); failed!";
break;
}
return pendingIO;
}
outStd[INSTANCES] 被定义为下面的 PIPE_HANDLES(一个自定义结构)
typedef struct
{
HANDLE hPipeInst;
OVERLAPPED o1;
TCHAR chReq[BUFSIZE];
TCHAR chReply[BUFSIZE];
DWORD dwRead;
DWORD dwWritten;
DWORD dwState;
DWORD cbRet;
BOOL pendingIO;
} PIPE_HANDLES, *LPSTDPIPE;
现在从这里开始,我有点迷路了。我不知道该去哪里。我尝试在 MSDN 示例中使用循环,但对于我想要做的事情,它不能正常工作。我需要获取管道的读取端并(再次,连续地)检索信息,同时在我可能需要写入它的时候打开一个写入端。有没有人有任何想法?我一直在尝试像使用匿名管道一样执行 ReadFile(),但它似乎并没有以相同的方式工作。
另外,请注意:代码有点草率,因为我一直在使用它,所以我很抱歉。在我让它正常运行后,我一定会清理它。
【问题讨论】:
-
ReadFile 到底有什么问题?命名管道和匿名管道打开后的工作方式相同。
-
出于我的目的,我已切换回匿名管道,但是,这似乎是两个相同的问题。它需要等到数据传输结束才能发送任何数据,所以我将继续研究它。
标签: c++ winapi asynchronous named-pipes