使用 WCF netNamedPipeBinding 時找不到命名管道
我是 WCF 服務的開發人員。我的測試客戶可以很好地使用它。但是當涉及到真正的客戶端(使用相同的客戶端代理)時,它會失敗。相同的 WCF 服務適用於 netTcpBinding,此錯誤僅發生在 netNamedPipeBinding 中,即使 ConcurrencyMode = ConcurrencyMode.Single
這是例外
在 net.pipe://localhost/MyService 上沒有可以接受消息的端點偵聽。這通常是由不正確的地址或 SOAP 操作引起的。有關更多詳細資訊,請參閱 InnerException(如果存在)。
伺服器堆棧跟踪:在
System.ServiceModel.Channels.PipeConnectionInitiator.GetPipeName(Uri uri) at System.ServiceModel.Channels.NamedPipeConnectionPoolRegistry.NamedPipeConnectionPool.GetPoolKey(EndpointAddress address, Uri via) at System.ServiceModel.Channels.CommunicationPool`2.TakeConnection(EndpointAddress address, Uri via , TimeSpan timeout, TKey& key) at System.ServiceModel.Channels.ConnectionPoolHelper.EstablishConnection(TimeSpan timeout) at System.ServiceModel.Channels.ClientFramingDuplexSessionChannel.OnOpen(TimeSpan timeout) at System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.OnOpen(TimeSpan timeout) 在 System.ServiceModel.Channels.CommunicationObject.Open(TimeSpan timeout) 在 System.ServiceModel.Channels.ServiceChannel。CallOnceManager.CallOnce(TimeSpan 超時,CallOnceManager 級聯)
在 System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout) 在 System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object
$$ $$ins, 對象$$ $$出,TimeSpan 超時)在 System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage 方法呼叫,ProxyOperationRuntime 操作)在 System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage 消息) 異常被重新拋出
$$ 0 $$:在 System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) 在 System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) 在
內部異常
PipeException:“在您的本地電腦上找不到管道端點 ’net.pipe://localhost/MyService’。”
堆棧跟踪顯示客戶端 WCF 通道堆棧在嘗試從服務 URL 派生服務使用的命名管道的實際名稱時失敗。該服務通過將一個小結構放置在包含 GUID 作為其欄位之一的命名共享記憶體部分中來發布管道名稱(這是一個每次服務重新啟動時都會更改的 GUID) 。用於共享記憶體部分的名稱是通過應用一種算法從服務 URL 派生的,該算法編譯到 NetNamedPipeBinding 的伺服器端和客戶端 WCF 程式碼中。
問題中報告的異常實際上意味著將算法應用於服務 URL 以提供名稱後,客戶端程式碼無法打開該名稱的共享記憶體部分的句柄。正如異常消息所述,這可能意味著沒有服務在偵聽用於派生名稱的服務 URL。但它可能意味著記憶體部分在那裡,服務也在那裡,但是客戶端程式碼沒有在允許它訪問共享記憶體的安全上下文中執行。
在 Vista 之前的 Windows 平台上,WCF 客戶端不太可能缺少打開共享記憶體、從中讀取管道名稱 GUID 並成功連接到服務管道的安全權限。但是在 Vista 和更高版本的平台上,有新的安全機制使得這成為更常見的故障場景。
Vista 為命名核心對象引入了不同命名空間的概念:每個登錄會話都有一個全域(機器範圍)命名空間和一個私有命名空間。NetNamedPipeBinding 客戶端程式碼將在查找通告管道名稱的共享記憶體部分時嘗試這兩個名稱空間。如果伺服器使用全域名稱創建了共享記憶體,或者如果服務和客戶端在同一個登錄會話中執行,那麼客戶端將找到它要查找的內容。但是,如果服務無法在全域命名空間中創建對象(它總是首先嘗試這樣做),那麼它將回退到創建私有會話命名空間,然後只有在同一會話中執行的客戶端才能看到它。在 Vista 和更高版本的平台中創建全域命名空間核心對象需要特殊權限,通常只有以“管理員身份”執行的 Windows 服務程序和應用程序才會擁有。一個常見的陷阱是嘗試在 Windows 服務中創建客戶端,並嘗試連接到在互動式使用者會話中執行的應用程序中託管的 WCF NetNamedPipe 服務。
如果客戶端程式碼在比託管服務的程式碼更低的完整性上下文(例如瀏覽器外掛)中執行,Vista 強製完整性機制還可以防止假定的客戶端連接到 WCF NetNamedPipeBinding 服務。
我想問題中報告的症狀,測試客戶端工作但真實客戶端不工作,幾乎可以肯定是由於這些原因中的一個或其他原因,真實客戶端的安全上下文與服務主機的安全上下文不一致。
如果搜尋此錯誤並遇到此文章,則解決此根本問題的另一種可能性 - 如果您收到
net.pipe在您的 url 中找不到地址的錯誤(即http://localhost:1234/MyService/etc/),請確保Net.Pipe 偵聽器適配器Windows 服務已啟動。(我也啟動了 Net.Tcp Listener Adapter)在某些情況下,該服務似乎沒有啟用或啟動,尤其是在部署到可能沒有安裝大量積極使用這些服務的開發工具的遠端伺服器時。啟動服務解決了這個問題。