我正在制作一个Win32应用程序,它通过命名管道将字符串从一个进程发送到另一个进程。但是,在管道上调用ReadFile的进程会得到其中包含一些乱码数据的字符串。它返回正确写入的字节数,但字符串的最后8个字符左右是乱码。
下面是创建管道和写入管道的代码:
myPipe = CreateNamedPipe(L"\\\\.\\pipe\\testpipe", PIPE_ACCESS_OUTBOUND, PIPE_NOWAIT, 10, 512, 512, 10, NULL);
TCHAR title[128];
GetWindowText(foundHwnd, title, 128);
wstring windowTitle(title);
vector<wstring> splitVec;
boost::split(splitVec, windowTitle, boost::algorithm::is_any_of(wstring(L"|")));
WriteFile(myPipe, splitVec[0].c_str(), splitVec[0].size(), &wrote, NULL);下面是读取它的代码:
if (WaitNamedPipe(L"\\\\.\\pipe\\testpipe", 5000) == 0) {
MessageBox(NULL, L"Unable to wait for pipe", L"Error", MB_OK);
return false;
}
myPipe = CreateFile(L"\\\\.\\pipe\\testpipe", GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (myPipe == INVALID_HANDLE_VALUE) {
MessageBox(NULL, L"Unable to open pipe", L"Error", MB_OK);
return false;
}
// Other code here...
TCHAR buf[512];
DWORD read;
success = ReadFile(myPipe, buf, 512, &read, NULL);
if (read > 0)
MessageBox(NULL, buf, L"Got Data", MB_OK);当显示MessageBox时,字符串的末尾是乱码,我不知道为什么。有什么想法吗?
谢谢!
发布于 2009-03-15 13:13:21
我认为这里的关键是确保您的字符串是null终止的,并且您也发送了终止字符。如果通信是同步的,或者如果是在PIPE_READMODE_MESSAGE中设置的,则不必发送整个缓冲区。当指定的字节数已被读取或在管道的另一端完成写入操作时,ReadFile将返回。我认为“乱码”文本实际上是管道客户端读取缓冲区中的垃圾,因为您没有传输字符串终止字符,所以它将其包含在发送到消息框的文本中。要么在发送前清除读缓冲区,要么随消息一起发送字符串终止字符,我认为这将在没有发送满缓冲区的开销的情况下工作。
这是来自微软的sample client。注意客户端如何准确地发送消息+ 1中的字符数(包括终止字符),并将其接收到大小为512的固定缓冲区中。如果你看一下server example,你会看到同样的模式。
发布于 2009-03-15 12:26:35
对您发布的代码的一些观察:
()+1。
尝试如下所示:
下面是创建管道和写入管道的代码:
myPipe = CreateNamedPipe(L"\\\\.\\pipe\\testpipe", PIPE_ACCESS_OUTBOUND, PIPE_NOWAIT, 10, 512, 512, 10, NULL);
TCHAR title[128];
GetWindowText(foundHwnd, title, 128);
WriteFile(myPipe, title, 128*sizeof(TCHAR), &wrote, NULL);//<---In this case we are sending a null terminated string buffer.下面是读取它的代码:
if (WaitNamedPipe(L"\\\\.\\pipe\\testpipe", 5000) == 0) {
MessageBox(NULL, L"Unable to wait for pipe", L"Error", MB_OK);
return false;
}
myPipe = CreateFile(L"\\\\.\\pipe\\testpipe", GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (myPipe == INVALID_HANDLE_VALUE) {
MessageBox(NULL, L"Unable to open pipe", L"Error", MB_OK);
return false;
}
// Other code here...
TCHAR buf[128];
DWORD read;
success = ReadFile(myPipe, buf, 128*sizeof(TCHAR), &read, NULL);
if (read > 0)
MessageBox(NULL, buf, L"Got Data", MB_OK);发布于 2015-07-01 22:38:12
当我编写一个泛型函数从命令提示符下执行的任何进程中读取stdout时,我遇到了这个“管道中的垃圾”问题。因此,我不能改变正在写入管道的内容(通常建议的那样),我只能改变读取端。所以,我“作弊”了。
如果管道数据没有以空终止符结束,我会用一个字符替换最后一个字符!它似乎对我很管用。在我的数据块末尾有空值和没有空值的情况下,我完美地看到了这一点。
我担心我可能会丢失关键的最后一个字符(您可能会丢失!),但对于我的直接目的来说,这并没有发生。在某些情况下,您可能会考虑添加null而不是替换结尾...
下面是代码片段:
const unsigned int MAX_PIPE_PEEKS = 100;
DWORD bytesInPipe = 0;
unsigned int pipePeeks=0;
while( (bytesInPipe==0) && (pipePeeks < MAX_PIPE_PEEKS) )
{
bSuccess = PeekNamedPipe( g_hChildStd_OUT_Rd, NULL, 0, NULL,
&bytesInPipe, NULL );
if( !bSuccess ) return bSuccess; // Bail on critical failure
++pipePeeks;
}
if( bytesInPipe > 0 )
{
// Read the data written to the pipe (and implicitly clear it)
DWORD dwRead;
CHAR *pipeContents = new CHAR[ bytesInPipe ];
bSuccess = ReadFile( g_hChildStd_OUT_Rd, pipeContents,
bytesInPipe, &dwRead, NULL );
if( !bSuccess || dwRead == 0 ) return FALSE; // Bail on critical failure
// "Cheat" - eliminate garbage at the end of the pipe
if( pipeContents[ bytesInPipe ] != '\0' )
pipeContents[ bytesInPipe ] = '\0';
}更新:
在进一步测试后,我发现这不太可靠(令人震惊,是吧?)。我认为我走在了一个相对简单的解决方案的正确轨道上。有什么办法让这个快速补丁生效吗?
https://stackoverflow.com/questions/647723
复制相似问题