从 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"
):
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" 可能返回了一个无效的句柄。如果确实存在这样的设备,它会返回设备的句柄,而不是命名管道实例。
在 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
, orCallNamedPipe
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 byPipeName
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"
):
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" 可能返回了一个无效的句柄。如果确实存在这样的设备,它会返回设备的句柄,而不是命名管道实例。