在IPC代码中,如果我通过调用CreateFile
使用Win32 API从命名管道获取句柄,一切正常。如果我使用NamedPipeClientStream
做同样的事情,它不想连接。
工作版
[DllImport("kernel32.dll")]
internal static extern SafePipeHandle CreateFile(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr securityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
public openPipe()
{
SafePipeHandle localDeviceHandle;
// Second Paameter is READ/WRITE Access, Fifth Parameter Open Existing
// This was done for brevity of the example.
localDeviceHandle = FileApi.CreateFile("\\\\.\\SeaMAC0",
(uint)3,
0,
IntPtr.Zero,
(uint)3,
(uint)FileApi.FileAttribute.Normal,
IntPtr.Zero);
}
不工作
public openPipe()
{
SeaLevelNamedPipe = new NamedPipeClientStream("SeaMAC0");
/*or SeaLevelNamedPipe = new NamedPipeClientStream(".","SeaMAC0");*/
SeaLevelNamedPipe.Connect(); //It will hang here for ever
}
这里的代码远非完整,为简洁起见。他们的功能不一样吗?
我无法访问服务器管道代码,因为这是由第三方开发的。
答案 0 :(得分:1)
在第一个“this works”示例中,您没有为lpFileName
参数使用有效的命名管道名称。这:"\\\\.\\SeaMAC0"
不是有效的命名管道名称。
请参阅documentation on Pipe Names:
在
CreateFile
,WaitNamedPipe
或CallNamedPipe
函数中指定管道名称时,请使用以下表单:\\ServerName\pipe\PipeName
其中
ServerName
是远程计算机的名称或句点,用于指定本地计算机。PipeName
指定的管道名称字符串可以包含反斜杠以外的任何字符,包括数字和特殊字符。整个管道名称字符串最长可达256个字符。管道名称不区分大小写。管道服务器无法在另一台计算机上创建管道,因此
CreateNamedPipe
必须使用句点作为服务器名称,如以下示例所示。\\.\pipe\PipeName
因此,在您的第二个“不起作用”示例中,.NET NamedPipeClientStream
将用于连接到服务器管道的构造管道名称是:
\\.\pipe\SeaMAC0
随后在调用WaitNamedPipe
Win32方法时尝试连接到命名管道服务器,在连接循环中,在调用Connect
时无限期超时。鉴于没有具有给定名称的管道服务器,它将完全按照您的描述结束:等待,永远孤独。
请注意,对于您使用过的文件名("\\\\.\\SeaMAC0"
):
"\\.\"
前缀将访问Win32设备命名空间而不是Win32文件命名空间。...
如果您使用的是Windows API函数,则应使用
"\\.\"
前缀仅访问设备,而不是文件。
所以,例如\\.\COM1
将打开COM1设备的句柄,\\.\DISPLAY1
代表默认的显示设备。如果SeaMAC0
不是系统上的实际设备名称,则“工作版本”可能会返回无效的句柄。如果这样的设备确实存在,它会返回设备的句柄,而不是命名的管道实例。