创建名为管道错误

Creating Named Pipe Error

本文关键字:错误 管道 创建      更新时间:2023-10-16

我正在创建一个命名的管道并使用函数来做到这一点。这是代码:

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(即管道繁忙)失败。我不明白为什么管道很忙,什么是创建管道的正确方法?在创建管道之前,邮政检查和预检查应该是什么?

您显示的代码都是错误的。

此检查:

if (INVALID_HANDLE_VALUE != tProviderPipe)

需要使用==而不是!=。如果CreateNamedPipe() 成功

,您的代码将失败。

此检查:

if (ERROR_PIPE_BUSY != GetLastError())

需要删除。首先,它位于错误的地方。GetLastError()仅在CreateNamedPipe() 失败时才有效。在上面进行==修复后,GetLastError()将在CreateNamedPipe()成功后永远不会是ERROR_PIPE_BUSY(或任何其他有意义的值)。其次,如果将其移至正在检查tProviderPipeif中,则它将变为多余

此检查:

if (!WaitNamedPipe(L"MyPipe", 20000))

也需要删除。首先,您将其传递给了错误的管道名称格式。其次,它旨在在调用CreateFile()之前命名 client (或者如果CreateFile()使用ERROR_PIPE_BUSY失败)。请勿在命名的管道 server 中调用它。您打算致电ConnectNamedPipe(),它等待客户端连接到您正在创建的 server 管道。

请查看MSDN上的命名管服务器示例。

尝试更多这样的东西:

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);