Named pipe not found when using WCF netNamedPipeBinding
I am the developer of a WCF service. My test clients work very well with it. But when it comes to real clients (using the same client proxy), it fails. The same WCF service works with netTcpBinding, this error occurs only with netNamedPipeBinding, even with ConcurrencyMode = ConcurrencyMode.Single
Here is the exception
There was no endpoint listening at net.pipe://localhost/MyService that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
Server stack trace: at
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) at System.ServiceMod开发者_如何学Goel.Channels.CommunicationObject.Open(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.CallOnceManager.CallOnce(TimeSpan timeout, CallOnceManager cascade)
at System.ServiceModel.Channels.ServiceChannel.EnsureOpened(TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout) at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation) at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at
Inner Exception
PipeException: "The pipe endpoint 'net.pipe://localhost/MyService' could not be found on your local machine. "
The stack trace shows that the client-side WCF channel stack failed when trying to derive from the service URL the actual name of the named pipe being used by the service. The service publishes the pipe name (which is a GUID which changes each time the service restarts) by placing a small structure in a named shared memory section which contains the GUID as one of its fields. The name used for the shared memory section is derived from the service URL by applying an algorithm which is compiled into both the server-side and client-side WCF code for the NetNamedPipeBinding.
The exception reported in the question really means that having applied the algorithm to the service URL to come up with a name, the client side code could not open a handle to a shared memory section of that name. This may mean, as the exception message states, that there is no service listening on the service URL used to derive the name. But it can instead mean that the memory section is there, and so is the service, but the client-side code is not running in a security context which allows it to access the shared memory.
On Windows platforms prior to Vista it is fairly unlikely that a WCF client would ever lack the security permissions to open the shared memory, read the pipe name GUID from it, and then successfully connect to the service's pipe. But on Vista and later platforms there are new security mechanisms which make this a much more common failure scenario.
Vista introduced a concept of different namespaces for named kernel objects: there is a Global (machine-wide) namespace, and a Private namespace for each logon session. The NetNamedPipeBinding client code will try both namespaces when looking for the shared memory section which advertises the pipe name. If the server has created the shared memory using a Global name, or if the service and the client are running in the same logon session, then the client will find what it is looking for. If, though, the service cannot create an object in the Global namespace (it always tries to do this first) then it will fall back to creating it the private session namespace, and then only clients running in the same session will be able to see it. Creating Global namespace kernel objects requires a special privilege in Vista and later platforms, which typically only Windows Service processes and applications running "As Administrator" will have. A common pitfall is to try to create a client in a Windows Service attempting to connect to a WCF NetNamedPipe service hosted in an application running in the interactive user session.
The Vista Mandatory Integrity Mechanism can also prevent a putative client connecting to a WCF NetNamedPipeBinding service, if the client code is running in a lower integrity context (e.g. a browser plug-in) than the code hosting the service.
I would imagine that the symptoms reported in the question, with test clients working but real clients not working, are almost certainly caused by the security context of the real clients being inconsistent with that of the service host, for one or other of these reasons.
Another possibility to fix this root issue if searching for this error and coming across this post - if you are getting an error that no net.pipe
address can be found at your url (i.e. http://localhost:1234/MyService/etc/
) make sure that the Net.Pipe Listener Adapter Windows Service is started. (I also started Net.Tcp Listener Adapter)
The service does not seem to be enabled or started in some scenarios especially when deploying out to a remote server that might not of had a lot of the development tools installed that actively use these services. Starting the service fixed the issue.
The endpoint used by your client has to match an endpoint exposed by your WCF service. This means that the address/binding/contract tuple of the specified client endpoint must exactly match the address/binding/contract tuple of an endpoint exposed by your WCF service. If you're using the app.config approach, make sure everything is spelled correctly in both the WCF service and client config files. If you are adding the endpoints programmatically, make sure you haven't misspelled anything in the code.
精彩评论