创建命名管道错误
Creating Named Pipe Error
我正在创建一个命名管道并使用一个函数来创建它。这是代码:
HANDLE tProviderPipe(INVALID_HANDLE_VALUE);
SECURITY_ATTRIBUTES tSecurityAttributes;
tSecurityAttributes.nLength = sizeof(tSecurityAttributes);
tSecurityAttributes.bInheritHandle = FALSE;
tSecurityAttributes.lpSecurityDescriptor = NULL;
while (1)
{
tProviderPipe = ::CreateNamedPipe(L"\\.\pipe\MyPipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
128,
128,
5000,
&tSecurityAttributes);
if (INVALID_HANDLE_VALUE != tProviderPipe)
{
DWORD lLastStatus(GetLastError());
OHTRACE(Trace::eTAlways, L"Pipe Status: " << (unsigned int)lLastStatus);
break;
}
if (ERROR_PIPE_BUSY != GetLastError())
{
DWORD lLastStatus(GetLastError());
OHTRACE(Trace::eTAlways, L"Pipe Status: " << (unsigned int)lLastStatus);
break;
}
if (!WaitNamedPipe(L"MyPipe", 20000))
{
DWORD lLastStatus(GetLastError());
OHTRACE(Trace::eTAlways, L"WPipe Status: " << (unsigned int)lLastStatus);
}
调用此函数时,管道创建失败,错误代码为 231(即管道忙)。我不明白为什么管道很忙,创建管道的正确方法是什么?在继续创建管道之前,post 检查和预检查应该是什么?
你显示的代码都是错误的。
此项检查:
if (INVALID_HANDLE_VALUE != tProviderPipe)
需要使用 ==
而不是 !=
。如果 CreateNamedPipe()
成功 .
,则您的代码失败
此项检查:
if (ERROR_PIPE_BUSY != GetLastError())
需要删除。首先,它在错误的地方。 GetLastError()
仅在 CreateNamedPipe()
失败 时有效。完成上述 ==
修复后,CreateNamedPipe()
成功后 GetLastError()
将永远不会是 ERROR_PIPE_BUSY
(或任何其他有意义的值)。其次,如果您将它移到正在检查 tProviderPipe
的 if
中,那么它就变得多余了,因为它记录的信息与已经在那里记录的信息相同。
此项检查:
if (!WaitNamedPipe(L"MyPipe", 20000))
也需要删除。首先,您向它传递了错误的管道名称格式。其次,它旨在让命名管道 client 在调用 CreateFile()
之前调用(或者如果 CreateFile()
因 ERROR_PIPE_BUSY
而失败)。不要在命名管道 server 中调用它。您打算改为调用 ConnectNamedPipe()
,它等待客户端连接到您正在创建的 server 管道。
请查看 MSDN 上的 named pipe server examples。
尝试更像这样的东西:
HANDLE tProviderPipe = INVALID_HANDLE_VALUE;
SECURITY_ATTRIBUTES tSecurityAttributes;
OVERLAPPED ov = {};
DWORD lLastStatus;
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ov.hEvent) {
lLastStatus = GetLastError();
OHTRACE(Trace::eTAlways, L"Pipe Event Create Error: " << (UINT)lLastStatus);
return;
}
tSecurityAttributes.nLength = sizeof(tSecurityAttributes);
tSecurityAttributes.bInheritHandle = FALSE;
tSecurityAttributes.lpSecurityDescriptor = NULL;
while (1) {
if (INVALID_HANDLE_VALUE == tProviderPipe) {
tProviderPipe = ::CreateNamedPipe(L"\\.\pipe\MyPipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 128, 128, 5000, &tSecurityAttributes);
if (INVALID_HANDLE_VALUE == tProviderPipe) {
lLastStatus = GetLastError();
OHTRACE(Trace::eTAlways, L"Pipe Create Error: " << (UINT)lLastStatus);
break;
}
}
if (!ConnectNamedPipe(tProviderPipe, &ov)) {
lLastStatus = GetLastError();
if (ERROR_IO_PENDING == lLastStatus) {
if (WaitForSingleObject(ov.hEvent, 20000) != WAIT_OBJECT_0) {
OHTRACE(Trace::eTAlways, L"Pipe not connected in 20 seconds");
break;
}
}
else if (ERROR_PIPE_CONNECTED != lLastStatus) {
OHTRACE(Trace::eTAlways, L"Pipe Connect Error: " << (UINT)lLastStatus);
continue;
}
}
// use tProviderPipe as needed ...
DisconnectNamedPipe(tProviderPipe);
}
if (INVALID_HANDLE_VALUE != tProviderPipe) {
CloseHandle(tProviderPipe);
}
CloseHandle(ov.hEvent);
我正在创建一个命名管道并使用一个函数来创建它。这是代码:
HANDLE tProviderPipe(INVALID_HANDLE_VALUE);
SECURITY_ATTRIBUTES tSecurityAttributes;
tSecurityAttributes.nLength = sizeof(tSecurityAttributes);
tSecurityAttributes.bInheritHandle = FALSE;
tSecurityAttributes.lpSecurityDescriptor = NULL;
while (1)
{
tProviderPipe = ::CreateNamedPipe(L"\\.\pipe\MyPipe",
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
1,
128,
128,
5000,
&tSecurityAttributes);
if (INVALID_HANDLE_VALUE != tProviderPipe)
{
DWORD lLastStatus(GetLastError());
OHTRACE(Trace::eTAlways, L"Pipe Status: " << (unsigned int)lLastStatus);
break;
}
if (ERROR_PIPE_BUSY != GetLastError())
{
DWORD lLastStatus(GetLastError());
OHTRACE(Trace::eTAlways, L"Pipe Status: " << (unsigned int)lLastStatus);
break;
}
if (!WaitNamedPipe(L"MyPipe", 20000))
{
DWORD lLastStatus(GetLastError());
OHTRACE(Trace::eTAlways, L"WPipe Status: " << (unsigned int)lLastStatus);
}
调用此函数时,管道创建失败,错误代码为 231(即管道忙)。我不明白为什么管道很忙,创建管道的正确方法是什么?在继续创建管道之前,post 检查和预检查应该是什么?
你显示的代码都是错误的。
此项检查:
if (INVALID_HANDLE_VALUE != tProviderPipe)
需要使用 ==
而不是 !=
。如果 CreateNamedPipe()
成功 .
此项检查:
if (ERROR_PIPE_BUSY != GetLastError())
需要删除。首先,它在错误的地方。 GetLastError()
仅在 CreateNamedPipe()
失败 时有效。完成上述 ==
修复后,CreateNamedPipe()
成功后 GetLastError()
将永远不会是 ERROR_PIPE_BUSY
(或任何其他有意义的值)。其次,如果您将它移到正在检查 tProviderPipe
的 if
中,那么它就变得多余了,因为它记录的信息与已经在那里记录的信息相同。
此项检查:
if (!WaitNamedPipe(L"MyPipe", 20000))
也需要删除。首先,您向它传递了错误的管道名称格式。其次,它旨在让命名管道 client 在调用 CreateFile()
之前调用(或者如果 CreateFile()
因 ERROR_PIPE_BUSY
而失败)。不要在命名管道 server 中调用它。您打算改为调用 ConnectNamedPipe()
,它等待客户端连接到您正在创建的 server 管道。
请查看 MSDN 上的 named pipe server examples。
尝试更像这样的东西:
HANDLE tProviderPipe = INVALID_HANDLE_VALUE;
SECURITY_ATTRIBUTES tSecurityAttributes;
OVERLAPPED ov = {};
DWORD lLastStatus;
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!ov.hEvent) {
lLastStatus = GetLastError();
OHTRACE(Trace::eTAlways, L"Pipe Event Create Error: " << (UINT)lLastStatus);
return;
}
tSecurityAttributes.nLength = sizeof(tSecurityAttributes);
tSecurityAttributes.bInheritHandle = FALSE;
tSecurityAttributes.lpSecurityDescriptor = NULL;
while (1) {
if (INVALID_HANDLE_VALUE == tProviderPipe) {
tProviderPipe = ::CreateNamedPipe(L"\\.\pipe\MyPipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED, PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT, 1, 128, 128, 5000, &tSecurityAttributes);
if (INVALID_HANDLE_VALUE == tProviderPipe) {
lLastStatus = GetLastError();
OHTRACE(Trace::eTAlways, L"Pipe Create Error: " << (UINT)lLastStatus);
break;
}
}
if (!ConnectNamedPipe(tProviderPipe, &ov)) {
lLastStatus = GetLastError();
if (ERROR_IO_PENDING == lLastStatus) {
if (WaitForSingleObject(ov.hEvent, 20000) != WAIT_OBJECT_0) {
OHTRACE(Trace::eTAlways, L"Pipe not connected in 20 seconds");
break;
}
}
else if (ERROR_PIPE_CONNECTED != lLastStatus) {
OHTRACE(Trace::eTAlways, L"Pipe Connect Error: " << (UINT)lLastStatus);
continue;
}
}
// use tProviderPipe as needed ...
DisconnectNamedPipe(tProviderPipe);
}
if (INVALID_HANDLE_VALUE != tProviderPipe) {
CloseHandle(tProviderPipe);
}
CloseHandle(ov.hEvent);