C#为只读命名管道(NamedPipeClientStream类)启用MessageMode时发生UnauthorizedAccessException
.NET中的C#为只读命名管道(NamedPipeClientStream类)启用MessageMode时发生UnauthorizedAccessException,c#,.net,named-pipes,C#,.net,Named Pipes,.NET中的NamedPipeClientStream类存在问题,因为您无法使用中的PipeDirection.in创建此类的实例,然后成功地将读取模式更改为PipeTransmissionMode.Message 尝试执行此操作将引发未经授权的访问异常。虽然管道通常用于进程之间的通信,但单个进程中的这个简单示例说明了问题: var pipeOut = new NamedPipeServerStream("SomeNamedPipe",
NamedPipeClientStream
类存在问题,因为您无法使用中的PipeDirection.in
创建此类的实例,然后成功地将读取模式
更改为PipeTransmissionMode.Message
尝试执行此操作将引发未经授权的访问异常。虽然管道通常用于进程之间的通信,但单个进程中的这个简单示例说明了问题:
var pipeOut = new NamedPipeServerStream("SomeNamedPipe",
PipeDirection.Out,
1,
PipeTransmissionMode.Message);
var pipeIn = new NamedPipeClientStream(".",
"SomeNamedPipe",
PipeDirection.In);
pipeIn.Connect();
pipeIn.ReadMode = PipeTransmissionMode.Message;
试图设置ReadMode属性时,此代码将抛出一个UnauthorizedAccessException
在搜索有关此问题的信息时,我在其他地方找到了对它的引用,例如:
我的问题是,为什么在入站管道上启用消息模式会导致异常,有没有比将管道更改为双向模式更好的方法来解决此问题?查看Microsoft参考源,我可以看到,设置
ReadMode
属性只是调用win32SetNamedPipeHandleState
函数来执行该操作,该调用产生的错误作为异常而引发。根据文档,它声明了要调用此函数所需的管道句柄
句柄必须具有对指定管道的通用写入访问权限
只写或读/写管道,或者它必须具有通用的\u读和
只读管道的文件\写入\属性访问
问题就在这里
如果我们查看接受PipeDirection
设置的NamedPipeClientStream的构造函数,我们会发现它们只请求GENERIC\u READ
访问PipeDirection.in
,和GENERIC\u WRITE
访问PipeDirection.Out
(或同时请求InOut
)。这意味着在Out
或InOut
模式下打开的任何管道都可以工作,因为GENERIC\u WRITE
访问对于这些情况是足够的,但是对于NamedPipeClientStream
类从不请求的只读管道,我们需要GENERIC\u READ
和FILE\u WRITE\u属性。这是类中的一个缺陷,应该由Microsoft更正
我已在此处提交了有关Microsoft Connect的错误报告:
如果您自己遇到此问题,请加快投票,这可能有助于加快修复速度
在修复之前(截至2017年3月无),您可以通过为NamedPipeClientStream
使用不同的构造函数来完全解决此问题
构造函数有一个重载,它接受的不是PipeDirection
枚举,而是PipeAccessRights
枚举,您可以指定要为句柄获取的访问权限的特定组合。然后,构造函数从指定的访问权限组合中导出管道的方向(In
如果指定了ReadData
,Out
“如果指定了WriteData
,InOut
,如果两者都指定了)
这意味着您可以解决此问题,而无需使管道全双工,只需更改以下构造函数行:
var pipeIn = new NamedPipeClientStream("<ServerName>", "<PipeName>", PipeDirection.In);
var pipeIn=newnamedpipeclientstream(“,”,PipeDirection.In);
为此:
var pipeIn =
new NamedPipeClientStream("<ServerName>",
"<PipeName>",
PipeAccessRights.ReadData | PipeAccessRights.WriteAttributes,
PipeOptions.None,
System.Security.Principal.TokenImpersonationLevel.None,
System.IO.HandleInheritability.None);
var pipeIn=
新名称PipeClientStream(“,
"",
PipeAccessRights.ReadData | PipeAccessRights.WriteAttributes,
没有选择,
System.Security.Principal.TokenImpersonationLevel.None,
System.IO.HandleInheritability.None);
如果使用此替代构造函数作为建议的解决方法,则结果将与从第一种构造函数中获得的结果相同且无法区分,唯一的例外是将获得此附加访问权限,以便启用消息模式。使用PipeDirecti肯定没有帮助在
on上,枚举的名称完全是向后命名的。您写入单向管道的输入端,数据沿着管道向下传输到另一个进程,然后可以从输出端读取。但是,PipeDirection。In
表示可读(管道的输出端).错误CS1729“NamedPipeServerStream”不包含接受6个参数的构造函数
@AlexG您需要对NamedPipeClientStream
进行这些更改,如图所示。您的错误表明您试图修改NamedPipeServerStream
。