命名管道从NamedPipeClientStream调用时不连接

时间:2015-05-21 22:03:55

标签: c# ipc

在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   
}

这里的代码远非完整,为简洁起见。他们的功能不一样吗?

我无法访问服务器管道代码,因为这是由第三方开发的。

1 个答案:

答案 0 :(得分:1)

在第一个“this works”示例中,您没有为lpFileName参数使用有效的命名管道名称。这:"\\\\.\\SeaMAC0"不是有效的命名管道名称。

请参阅documentation on Pipe Names

  

CreateFileWaitNamedPipeCallNamedPipe函数中指定管道名称时,请使用以下表单:

\\ServerName\pipe\PipeName
     

其中ServerName是远程计算机的名称或句点,用于指定本地计算机。 PipeName指定的管道名称字符串可以包含反斜杠以外的任何字符,包括数字和特殊字符。整个管道名称字符串最长可达256个字符。管道名称不区分大小写。

     

管道服务器无法在另一台计算机上创建管道,因此CreateNamedPipe必须使用句点作为服务器名称,如以下示例所示。

\\.\pipe\PipeName

因此,在您的第二个“不起作用”示例中,.NET NamedPipeClientStream将用于连接到服务器管道的构造管道名称是:

\\.\pipe\SeaMAC0

随后在调用WaitNamedPipe Win32方法时尝试连接到命名管道服务器,在连接循环中,在调用Connect时无限期超时。鉴于没有具有给定名称的管道服务器,它将完全按照您的描述结束:等待,永远孤独。

请注意,对于您使用过的文件名("\\\\.\\SeaMAC0"):

  

Win32 Device Namespaces

     

"\\.\"前缀将访问Win32设备命名空间而不是Win32文件命名空间。

     

...

     

如果您使用的是Windows API函数,则应使用"\\.\"前缀仅访问设备,而不是文件。

所以,例如\\.\COM1将打开COM1设备的句柄,\\.\DISPLAY1代表默认的显示设备。如果SeaMAC0不是系统上的实际设备名称,则“工作版本”可能会返回无效的句柄。如果这样的设备确实存在,它会返回设备的句柄,而不是命名的管道实例。