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

Named Pipe Not connecting when being called from NamedPipeClientStream

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

此处的代码远未完成,为简洁起见。它们的功能不应该相同吗?

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

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

参考documentation on Pipe Names:

Use the following form when specifying the name of a pipe in the CreateFile, WaitNamedPipe, or CallNamedPipe function:

\ServerName\pipe\PipeName

where ServerName is either the name of a remote computer or a period, to specify the local computer. The pipe name string specified by PipeName can include any character other than a backslash, including numbers and special characters. The entire pipe name string can be up to 256 characters long. Pipe names are not case-sensitive.

The pipe server cannot create a pipe on another computer, so CreateNamedPipe must use a period for the server name, as shown in the following example.

\.\pipe\PipeName

因此,在您的第二个 "does not work" 示例中,.NET NamedPipeClientStream 将用于连接到服务器管道的构造管道名称是:

\.\pipe\SeaMAC0

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

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

Win32 Device Namespaces

The "\.\" prefix will access the Win32 device namespace instead of the Win32 file namespace.

...

If you're working with Windows API functions, you should use the "\.\" prefix to access devices only and not files.

例如\.\COM1会打开一个COM1设备的句柄,\.\DISPLAY1代表默认的显示设备。如果 SeaMAC0 不是您系统上的实际设备名称,您的 "Working Version" 可能返回了一个无效的句柄。如果确实存在这样的设备,它会返回设备的句柄,而不是命名管道实例。