команды, такие как CreateFile ("\\ mycomputer \ mailslot \ this_fails", ...), завершаются с последней ошибкой = 53 ERROR_BAD_NETPATH
Сбой при использовании с любым действительным или несуществующим именем компьютера, включая имя компьютератот же компьютер, на котором выполняется тест.На компьютерах, где это работает, он завершается успешно и возвращает дескриптор почтового ящика, даже если указанный компьютер не существует или не имеет почтового ящика, созданного с таким именем.Обратите внимание, что если используется несуществующее имя компьютера или почтовый слот, последующие WriteFiles на дескрипторе завершатся с ошибкой, но CreateFile все-таки преуспеет.
Однако приведенный выше CreateFile завершится успешно, если ссылка на Mailslot явно локальна: "\\. \ mailslot \ always_works "
Это работало на всех версиях Windows ранее, пока не были установлены накопительные обновления 2018-05.Именно KB4103721 (Windows 10 home) казалось виновником.[Редактировать: как отмечено в ответах ниже, эта проблема на самом деле является сборкой обновления компонента 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;
}
Тестовый сервер: (читает отображаемые отправленные сообщения) Обратите внимание, что повторяющиеся сообщения могут быть получены, посколькуСообщения почтовых ящиков передаются по всем возможным протоколам.На основе 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] = '\0';
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 на одном компьютере или запускать на разныхкомпьютеры.Когда происходит сбой, он сразу же выходит из строя и, по-видимому, является проблемой при попытке определить имя сетевого пути.На том же компьютере общие файловые ресурсы, такие как \\ ThisComputer \ share, работают правильно с того же компьютера или с другого компьютера.
NetBIOS включен через TCP / IP для используемых сетевых адаптеров.Сетевые адаптеры обозначены как частные.Брандмауэр был отключен для тестирования.Общий доступ к файлам и принтерам включен.Компьютеры находятся в одной рабочей группе.Разрешение имени компьютера работает, и это не удается, даже если используются IP-адреса (даже 127.0.0.1).