本文介绍了第三方应用程序破坏我们的WCF应用程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时删除!!

我们的应用程序使用WCF命名管道两个进程之间的通信(注:无论过程是一个Windows服务。)我们的应用程序已经在该领域已经运行无事了几年现在

我们现在收到的报告,一个第三方应用程序(特别是,Garmin的防爆preSS)的presence是打破我们的。我在家里安装了Garmin的防爆preSS和确认的行为。明确了Garmin的核心更新服务,在运行的时候,使我们的应用程序失败。

在Garmin的服务正在运行我们的应用程序启动时,服务的一面,也没有问题,创建WCF终结。但是,当客户端启动并尝试连接到该服务,它失败EndpointNotFoundException,仿佛服务甚至没有运行

在这一点上,我可以从字面上停止从服务控制面板Garmin的服务,然后重新运行客户端成功,甚至没有重新启动我们自己的服务。如果我再次启动Garmin的服务,进一步尝试启动客户端失败。因此,这至少证明了我们的WCF服务启动和运行的整个时间,和Garmin的软件以某种方式阻止连接到该客户的能力。

我们正在用我们自己的名义为端点地址(例如像net.pipe://本地主机/ MyPrivateApplication)。我试图改变这个地址,以各种其他的名字,但对这个问题没有影响。

如何可以在另一个应用程序,只需通过运行,打破使用WCF我们自己的应用程序的能力?

更新:根据要求,这里是从服务端一个code段。我已经从原来的code,试图找出问题简单化了。到目前为止,没有我做了一个变化已经对这个问题有什么影响。

 为MyService服务=新的MyService();
ServiceHost的主机=新的ServiceHost(服务);
字符串hostAddress =新的URI(net.pipe://本地主机/ MyWCFConnection);
host.AddServiceEndpoint(typeof运算(IMyService),新NetNamedPipeBinding(),hostAddress);
host.Open();
 

解决方案

一个可能的回答你的问题怎样才能另一个应用程序,只需通过运行,打破了自己的应用程序。

  1. 在其他应用程序也使用WCF NetNamedPipeBinding。
  2. 在这两个应用程序创建一个使用基地+相对URL服务端点。
  3. 的应用程序的选择的基地址,并且HostNameComparisonMode是使得存在于one所使用的客户端的WCF栈来定位的元数据服务的网址的变体。

我不知道Garmin的服务是否实际执行使用WCF NetNamedPipeBinding,但是这是一种可能性,你应该调查。可以通过始终使用的NetNamedPipe端点绝对URL回避的问题。


好了,下面的更新的问题,我们现在知道Garmin的服务使用WCF NetNamedPipeBinding,我们知道你的应用程序注册使用绝对地址的服务,所以上面的解释是不完整的故事。

下面是另一种假说:

  1. 假设Garmin的服务运行在一个过程,具有安全保密SeCreateGlobalPrivilege(​​其中一个Windows服务将有除非特别codeD禁用的特权)。
  2. 在假定它也注册了WCF的命名管道终点与net.pipe的基址:// localhost,且相对端点地址
  3. 现在,它的服务元数据将被使用共享内存映射对象,在全局命名空间的名称出版。
  4. 您的服务应用程序不是Windows服务。我的假设是,它的进程不具有的安全保密SeCreateGlobalPrivilege。如果是这样的话,它的服务元数据将在仅其本地会话命名空间使用共享存储器映射对象被公开。
  5. 现在,您的客户端进程试图启动Garmin的服务正在运行时,连接...的WCF客户端通道堆栈NetNamedPipeBinding元素尝试根据您的服务URL net.pipe定位服务元数据为您服务://本地主机/ MyWCFConnection。如在上面的链接所解释的,这将依次使用的服务URL的各种变体导出的名称包含元数据的共享存储器对象执行搜索。它看起来在全局命名空间为先,又变的完整列表,寻找到本地命名空间之前。
  6. 在这种情况下,在第一次尝试将是从net.pipe:// + / MyWCFConnection衍生的名称。,和psumably它未能找到的对象与在全局命名空间此名称$ P $
  7. 然而,第二次尝试将根据变种net.pipe:// + /,而这将匹配刊登在全局命名空间Garmin的服务的共享内存映射的名称,它永远不会公布本地会话命名空间服务的元数据。
  8. 您的客户端试图连接到Garmin的服务的管道。让我们假设Garmin的服务有一定的安全实施,导致在客户端被拒绝与被拒绝访问(例如,它可set其管的ACL)。结果很可能表面作为EndpointNotFoundException。 [以后编辑:其实,最有可能正在发生的事情是,你的客户端实际连接到Garmin的服务,启动成帧协议的preamble握手,并接受背部框架协议故障(http://schemas.microsoft.com/ws/2006/05/framing/faults/EndpointNotFound)因为在通过记录请求的URL将不匹配什么Garmin的服务期望,绑定,然后丢弃连接和堆焊此故障到客户端code作为一种EndpointNotFoundException。]

你能做些什么呢?我建议:

  • 如果上述假设或类似的东西可以确认,和Garmin使用基地+相对只有net.pipe的基址://本地主机,最好的办法是让他们对自己这个问题:他们能解决这样的一个问题很容易地通过改变其基地址的东西更可能是唯一的。
  • 您也许可以解决它通过寻找一些方法为您服务应用程序使用的安全保密SeCreateGlobalPrivilege运行:这是不容易的,而不使它成为一个Windows服务或以管理员身份运行,但也许并非不可能。那么你的元数据也将公布在全局命名空间和客户端的搜索将之前的Garmin的找到它。
  • [后来编辑] 也许有涉及设置结合准确,使用的代名词localhost作为服务URL的主机部分(如net.pipe的HostNameComparisonMode属性的解决方法: //127.0.0.1/MyWCFConnection)。这可能会引导搜索周围的Garmin的变种,使您的客户端必须考虑名称的本地会话命名空间的机会。我不知道它会工作,但值得一试,我还以为。
  • 和一个非常长镜头:贵公司是否有与微软产品支持的关系?可以说这是一个严重的设计缺陷在WCF:如果你上做文章这件事,你有可能会得到Microsoft发布QFE补丁就如提供绑定属性来告诉客户端堆栈只尝试本地命名空间。

Our application uses WCF over named pipes to communicate between two processes (note: neither process is a Windows Service.) Our application has been running in the field without incident for a couple of years now.

We are now receiving reports that the presence of a third party application (specifically, Garmin Express) is breaking ours. I've installed Garmin Express in house and confirmed the behavior. Specifically the "Garmin Core Update Service", when running, causes our application to fail.

When the Garmin service is running, the "service" side of our application starts and has no problems creating the WCF endpoint. But when the client starts and attempts to connect to the service, it fails with EndpointNotFoundException, as if the service is not even running.

At this point, I can literally stop the Garmin service from the Services control panel, then re-run the client successfully without even restarting our own service. If I start the Garmin service again, further attempts to start the client fail. So this at least proves that our WCF service is up and running the whole time, and the Garmin software is somehow blocking our client's ability to connect to it.

We are using our own name for the endpoint address (e.g. something like "net.pipe://localhost/MyPrivateApplication"). I've tried changing this address to various other names, but that has no effect on the issue.

How can another application, simply by running, break our own application's ability to use WCF?

Update: by request, here is a code snippet from the service side. I've simplified it from our original code in an attempt to isolate the issue. So far, not a single change I've made has had any effect on the issue.

MyService service = new MyService();
ServiceHost host = new ServiceHost(service);
string hostAddress = new Uri("net.pipe://localhost/MyWCFConnection");
host.AddServiceEndpoint(typeof(IMyService), new NetNamedPipeBinding(), hostAddress);
host.Open();
解决方案

One possible answer to your question "How can another application, simply by running, break our own application...":

  1. The other application also uses the WCF NetNamedPipeBinding.
  2. Both applications create service endpoints using base + relative URLs.
  3. The applications' choice of base address, and HostNameComparisonMode is such that there is a name collision between the applications on one of the URL variants used by the client-side WCF stack to locate the metadata for the service.

I have no idea whether the Garmin service actually does use WCF NetNamedPipeBinding, but this is one possibility you should investigate. The problem can be avoided by always using absolute URLs for NetNamedPipe endpoints.


OK, so following the updates to the question, we now know that the Garmin service is using WCF NetNamedPipeBinding, and we know that your application registers its service using an absolute address, so the above explanation is not the complete story.

Here is another hypothesis:

  1. Suppose the Garmin service runs in a process which has the security privilege SeCreateGlobalPrivilege (which a Windows service will have unless specially coded to disable the privilege).
  2. Suppose it also registers its WCF Named Pipe endpoint with a base address of net.pipe://localhost and relative endpoint addresses.
  3. Now its service metadata will be published using a shared memory mapping object with a name in the Global namespace.
  4. Your service application is not a Windows service. My hypothesis is that its process does not have the security privilege SeCreateGlobalPrivilege. If this is the case, its service metadata will be published using a shared memory mapping object in its Local session namespace only.
  5. Now your client process tries to initiate a connection when the Garmin service is running... the WCF client-side channel stack NetNamedPipeBinding element tries to locate the service metadata for your service based on your service URL net.pipe://localhost/MyWCFConnection. As explained in the link above, it will execute the search using various variants of the service URL in turn to derive a name for the shared memory object containing the metadata. It looks in the Global namespace first, for the full list of variants in turn, before looking into the Local namespace.
  6. In this case, the first attempt will be for the name derived from "net.pipe://+/MyWCFConnection", and presumably it fails to find an object with this name in the Global namespace.
  7. However, the second attempt will be based on the variant "net.pipe://+/", and this will match the name of the Garmin service's shared memory mapping published in the Global namespace. Because of the search order, it will never get to your service's metadata published in the Local session namespace.
  8. Your client attempts to connect to the Garmin service's pipe. Let's assume the Garmin service has some security implemented which results in your client being rebuffed with an Access Denied (e.g. it may set an ACL on its pipe). The result might well surface as an EndpointNotFoundException. [LATER EDIT: Actually, most likely what is happening is that your client is actually connecting to the Garmin service, initiating the framing protocol's preamble handshake, and receiving back a framing protocol fault (http://schemas.microsoft.com/ws/2006/05/framing/faults/EndpointNotFound) because the URL requested in the Via record won't match what the Garmin service is expecting. The binding is then dropping the connection and surfacing this fault to your client code as an EndpointNotFoundException.]

What can you do about it? I would suggest:

  • If the above hypothesis or something similar can be confirmed, and Garmin are using base+relative addressing with a base of just net.pipe://localhost, best would be to get them to own the problem: they could fix such a problem very easily by changing their base address to something more likely to be unique.
  • You could perhaps work around it by finding some way for your service application to run with the security privilege SeCreateGlobalPrivilege: this isn't easy without making it a Windows service or running As Administrator, but maybe not impossible. Then your metadata would also be published in the Global namespace and the client's search would find it before Garmin's.
  • [Later edit] Maybe there is a workaround involving setting the HostNameComparisonMode property of the binding to Exact, and using a synonym for localhost as the host part of the service URL (e.g. net.pipe://127.0.0.1/MyWCFConnection). This may steer the search around the Garmin variants so that your client has a chance to consider names in the Local session namespace. I don't know that it will work, but worth a try, I would have thought.
  • And a very long shot: Does your company have a product support relationship with Microsoft? Arguably this is a serious design flaw in WCF: if you make a fuss about it you might possibly get Microsoft to issue a QFE patch for it e.g. to provide a binding property to tell the client-side stack to only try the Local namespace.

这篇关于第三方应用程序破坏我们的WCF应用程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

1403页,肝出来的..

09-07 00:11