[英]Named pipe C# using .NET 3.5 features like NamedPipeClientStream
[英]C# UnauthorizedAccessException when enabling MessageMode for read-only named pipe (NamedPipeClientStream class)
.NET中的NamedPipeClientStream
類存在問題,因為您無法使用PipeDirection.In
創建此類的實例,然后成功將ReadMode
更改為PipeTransmissionMode.Message
。
嘗試這樣做會引發UnauthorizedAccessException
。 雖然管道通常用於在進程之間進行通信,但是在單個進程中的這個簡單示例顯示了問題:
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
。
在搜索有關此問題的信息時,我在其他地方找到了對它的引用,例如:
所有這些帖子都提到這是“奇怪的”,“奇怪的”等,但不解釋“為什么”它不起作用,並且都給出相同的解決方法,“出於某種奇怪的原因”設置管道方向到InOut
使它工作。
確實,這確實使它工作,但它需要從根本上改變管道的兩端定義到全雙工,而不是單向,我認為這是一個非常差的方法,除非你是能夠改變客戶端和服務器,這甚至可能是不可能的。
我的問題是,為什么在入站管道上啟用消息模式會導致異常,是否有更好的方法來解決此問題,而不是將管道更改為雙向模式?
查看Microsoft參考源,我可以看到設置ReadMode
屬性只是調用win32 SetNamedPipeHandleState
函數來執行操作,此調用的錯誤作為異常引發。 根據文檔SetNamedPipeHandleState函數,它說明了管道句柄,以便調用此函數
句柄必須具有對只讀或讀/寫管道的命名管道的GENERIC_WRITE訪問權限,或者對於只讀管道必須具有GENERIC_READ和FILE_WRITE_ATTRIBUTES訪問權限。
這就是問題所在。
如果我們看一下構造函數NamedPipeClientStream是參加一個PipeDirection
設置,我們可以看到,他們只要求GENERIC_READ
訪問PipeDirection.In
和GENERIC_WRITE
訪問PipeDirection.Out
(或兩者InOut
)。 這意味着以Out
或InOut
模式打開的任何管道都可以工作,因為GENERIC_WRITE
訪問對於這些情況就足夠了,但我們需要GENERIC_READ
和FILE_WRITE_ATTRIBUTES
作為只讀管道, NamedPipeClientStream
類從不請求。 這是課堂上的缺陷,應由Microsoft更正。
我在這里提交了有關Microsoft Connect的錯誤報告:
https://connect.microsoft.com/VisualStudio/feedback/details/1825187
如果您自己遇到此問題,請向上投票,這可能有助於加快修復速度。
直到修復(從2017年3月開始沒有),人們可以通過為NamedPipeClientStream
使用不同的構造函數來完全解決這個問題。
還有,它接受,而不是一個構造函數的一個重載PipeDirection
枚舉,一個PipeAccessRights
枚舉相反,在那里你可以指定你想獲得手柄的訪問權限的特定組合。 構造函數然后導出管的從指定的訪問權的組合(該方向In
如果ReadData
被指定時, Out
“如果WriteData
被指定時, InOut
如果它們都指定)。
這意味着,您可以通過簡單地更改構造函數行來解決此問題,而無需使管道全雙工:
var pipeIn = new NamedPipeClientStream("<ServerName>", "<PipeName>", PipeDirection.In);
對此:
var pipeIn =
new NamedPipeClientStream("<ServerName>",
"<PipeName>",
PipeAccessRights.ReadData | PipeAccessRights.WriteAttributes,
PipeOptions.None,
System.Security.Principal.TokenImpersonationLevel.None,
System.IO.HandleInheritability.None);
如果您使用此備用構造函數作為建議的解決方法,則結果將與您從構造函數的第一種形式獲得的結果相同且無法區分,除了將獲得此附加訪問權限,以便消息模式可以是啟用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.