在 2018-05 Windows 10 功能更新 1803 之后,邮槽上的 CreateFile 失败并出现错误 53 ERROR_BAD_NETPATH

CreateFile on Mailslot fails with Error 53 ERROR_BAD_NETPATH after 2018-05 Windows 10 Feature Update 1803

CreateFile("\\mycomputer\mailslot\this_fails",...) 等命令失败,最后一个错误 = 53 ERROR_BAD_NETPATH

如果与任何有效或不存在的计算机名称一起使用,包括测试 运行ning 所在的同一台计算机,则会失败。在这行得通的计算机上,即使引用的计算机不存在或没有使用该名称创建的邮槽,它也会成功并且 returns 一个邮槽句柄。请注意,如果使用了不存在的计算机名称或邮槽,句柄上的后续 WriteFiles 将失败,但 CreateFile 会成功。

但是,如果 Mailslot 引用明确是本地的,则上面的 CreateFile 将成功:“\\.\mailslot\always_works”

这适用于之前所有版本的 Windows,直到安装了 2018-05 累积更新。特别是 KB4103721(Windows 10 家)似乎是罪魁祸首。 [编辑:如以下答案所述,实际上是功能更新版本 1803 导致了此问题。]

测试客户端:(在没有参数或“.”的情况下工作,但在任何计算机名下都失败)。 基于 msdn sample

语法:testclient [服务器计算机名]

    #include <windows.h>
    #include <stdio.h>
    #include <tchar.h>

    LPTSTR SlotName = TEXT("\\%hs\mailslot\sample_mailslot");

    BOOL WriteSlot(HANDLE hSlot, LPTSTR lpszMessage)
    {
       BOOL fResult;
       DWORD cbWritten;

       fResult = WriteFile(hSlot,
         lpszMessage,
         (DWORD) (lstrlen(lpszMessage)+1)*sizeof(TCHAR),
         &cbWritten,
         (LPOVERLAPPED) NULL);

       if (!fResult)
       {
// this failure is valid if computername is not valid
          printf("WriteFile failed with %d.\n", GetLastError());
          return FALSE;
       }

       printf("Slot written to successfully.\n");

       return TRUE;
    }

    int main(int nArgs,char * arg[])
    {
       HANDLE hFile;
       TCHAR szSlot[256];

       _stprintf (szSlot,SlotName,nArgs > 1 ? arg[1] : ".");

       _tprintf(TEXT("Writing to slot %s\n"),szSlot);
       hFile = CreateFile(szSlot,
         GENERIC_WRITE,
         FILE_SHARE_READ,
         (LPSECURITY_ATTRIBUTES) NULL,
         OPEN_EXISTING,
         FILE_ATTRIBUTE_NORMAL,
         (HANDLE) NULL);

       if (hFile == INVALID_HANDLE_VALUE)
       {
// this is the failure I'm trying to debug
          printf("CreateFile failed with %d.\n", GetLastError());
          return FALSE;
       }

       WriteSlot(hFile, TEXT("Message one for mailslot."));
       WriteSlot(hFile, TEXT("Message two for mailslot."));
       Sleep(5000);
       WriteSlot(hFile, TEXT("Message three for mailslot."));
       CloseHandle(hFile);

       return TRUE;
    }

测试服务器:(读取显示已发送的消息) 请注意,可能会收到重复的消息,因为 Mailslot 消息是通过所有可能的协议传输的。基于 msdn sample.

#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <strsafe.h>

HANDLE hSlot;
LPTSTR SlotName = TEXT("\\.\mailslot\sample_mailslot");

BOOL ReadSlot()
{
    DWORD cbMessage, cMessage, cbRead;
    BOOL fResult;
    LPTSTR lpszBuffer;
    TCHAR achID[80];
    DWORD cAllMessages;
    HANDLE hEvent;
    OVERLAPPED ov;

    cbMessage = cMessage = cbRead = 0;

    hEvent = CreateEvent(NULL, FALSE, FALSE, TEXT("ExampleSlot"));
    if( NULL == hEvent )
        return FALSE;
    ov.Offset = 0;
    ov.OffsetHigh = 0;
    ov.hEvent = hEvent;

    fResult = GetMailslotInfo( hSlot, // mailslot handle
        (LPDWORD) NULL,               // no maximum message size
        &cbMessage,                   // size of next message
        &cMessage,                    // number of messages
        (LPDWORD) NULL);              // no read time-out

    if (!fResult)
    {
        printf("GetMailslotInfo failed with %d.\n", GetLastError());
        return FALSE;
    }

    if (cbMessage == MAILSLOT_NO_MESSAGE)
    {
        printf("Waiting for a message...\n");
        return TRUE;
    }

    cAllMessages = cMessage;

    while (cMessage != 0)  // retrieve all messages
    {
        // Create a message-number string.

        StringCchPrintf((LPTSTR) achID,
            80,
            TEXT("\nMessage #%d of %d\n"),
            cAllMessages - cMessage + 1,
            cAllMessages);

        // Allocate memory for the message.

        lpszBuffer = (LPTSTR) GlobalAlloc(GPTR,
            lstrlen((LPTSTR) achID)*sizeof(TCHAR) + cbMessage);
        if( NULL == lpszBuffer )
            return FALSE;
        lpszBuffer[0] = '[=13=]';

        fResult = ReadFile(hSlot,
            lpszBuffer,
            cbMessage,
            &cbRead,
            &ov);

        if (!fResult)
        {
            printf("ReadFile failed with %d.\n", GetLastError());
            GlobalFree((HGLOBAL) lpszBuffer);
            return FALSE;
        }

        // Concatenate the message and the message-number string.
        StringCbCat(lpszBuffer,
                    lstrlen((LPTSTR) achID)*sizeof(TCHAR)+cbMessage,
                    (LPTSTR) achID);

        // Display the message.
        _tprintf(TEXT("Contents of the mailslot: %s\n"), lpszBuffer);

        GlobalFree((HGLOBAL) lpszBuffer);

        fResult = GetMailslotInfo(hSlot,  // mailslot handle
            (LPDWORD) NULL,               // no maximum message size
            &cbMessage,                   // size of next message
            &cMessage,                    // number of messages
            (LPDWORD) NULL);              // no read time-out

        if (!fResult)
        {
            printf("GetMailslotInfo failed (%d)\n", GetLastError());
            return FALSE;
        }
    }
    CloseHandle(hEvent);
    return TRUE;
}

BOOL WINAPI MakeSlot(LPTSTR lpszSlotName)
{
    hSlot = CreateMailslot(lpszSlotName,
        0,                             // no maximum message size
        MAILSLOT_WAIT_FOREVER,         // no time-out for operations
        (LPSECURITY_ATTRIBUTES) NULL); // default security

    if (hSlot == INVALID_HANDLE_VALUE)
    {
        printf("CreateMailslot failed with %d\n", GetLastError());
        return FALSE;
    }
    return TRUE;
}

void main()
{
   MakeSlot(SlotName);

   while(TRUE)
   {
      ReadSlot();
      Sleep(3000);
   }
}

测试服务器读取消息,测试客户端发送消息可以运行在同一台电脑的不同cmd shell,也可以运行在不同电脑。当它失败时,它立即失败并且似乎是尝试解析网络路径名的问题。在同一台计算机上,\\ThisComputer\share 等文件共享可以在同一台计算机或不同计算机上正常工作。

已通过 TCP/IP 为正在使用的网络适配器启用 NetBIOS。网络适​​配器被指定为专用。防火墙被禁用以进行测试。文件和打印机共享已启用。计算机在同一个工作组中。计算机名称解析有效,即使使用 IP 地址(甚至 127.0.0.1)也会失败。

这似乎是来自 Windows 10 (1803) 的最新功能更新的问题,而不是通过 Windows 更新的补丁。 请检查您是否使用 build 17134.48(也称为 1803)

尝试降级到 1709。

2019 年 1 月 9 日: 最新的 1809 Build Mailslots 又开始工作了

我没有找到任何信息表明您这样做不再支持邮槽通信。 我认为这是一个错误。 但找出答案的唯一方法是通过 support.microsoft.com.

打开支持票

或者您可以 post 这里 https://social.technet.microsoft.com/Forums

在我们从 Microsoft 获得任何新信息之前,所有需要邮槽的人都应该阻止功能升级 1803。

这个问题从去年开始就已经解决了

September 26, 2018—KB4458469 (OS Build 17134.320)

Addresses an issue that causes NTLTEST, DCLOCATOR, or joining an Active Directory and SAMBA domain to fail when using the NetBIOS domain name. The error is “An Active Directory domain Controller (AD DC) for the domain %domain% could not be contacted”. This also addresses connection issues for applications that use mailslots to communicate.