25

我们的应用程序在命名管道上使用 WCF 在两个进程之间进行通信(注意:这两个进程都不是 Windows 服务。)我们的应用程序已经在该领域运行了几年而没有发生任何事故。

我们现在收到报告称第三方应用程序(特别是 Garmin Express)的存在正在破坏我们的应用程序。我已经在内部安装了 Garmin Express 并确认了该行为。具体来说,“Garmin 核心更新服务”在运行时会导致我们的应用程序失败。

当 Garmin 服务运行时,我们应用程序的“服务”端启动并且创建 WCF 端点没有问题。但是当客户端启动并尝试连接到服务时,它会因 EndpointNotFoundException 而失败,就好像服务甚至没有运行一样。

此时,我可以从服务控制面板中停止 Garmin 服务,然后成功重新运行客户端,甚至无需重新启动我们自己的服务。如果我再次启动 Garmin 服务,则进一步尝试启动客户端会失败。所以这至少证明了我们的 WCF 服务一直在运行,并且 Garmin 软件以某种方式阻止了我们的客户端连接到它的能力。

我们使用自己的名称作为端点地址(例如“net.pipe://localhost/MyPrivateApplication”)。我已尝试将此地址更改为其他各种名称,但这对问题没有影响。

另一个应用程序怎么可能仅仅通过运行就破坏我们自己的应用程序使用 WCF 的能力?

更新:根据要求,这是来自服务端的代码片段。我已经从我们的原始代码中对其进行了简化,以试图隔离问题。到目前为止,我所做的任何更改都没有对这个问题产生任何影响。

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();
4

3 回答 3

16

您的问题“另一个应用程序如何通过运行来破坏我们自己的应用程序......”的一个可能答案:

  1. 另一个应用程序也使用 WCF NetNamedPipeBinding。
  2. 两个应用程序都使用基本 URL + 相对 URL 创建服务端点。
  3. 应用程序对基地址和 HostNameComparisonMode 的选择使得在客户端 WCF 堆栈用于定位服务元数据的 URL 变体之一上的应用程序之间存在名称冲突。

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


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

这是另一个假设:

  1. 假设 Garmin 服务在具有安全特权 SeCreateGlobalPrivilege 的进程中运行(Windows 服务将拥有该特权,除非经过特殊编码以禁用该特权)。
  2. 假设它还使用 net.pipe://localhost 的基地址和相对端点地址注册其 WCF 命名管道端点。
  3. 现在,它的服务元数据将使用共享内存映射对象发布,该​​对象具有全局命名空间中的名称。
  4. 您的服务应用程序不是 Windows 服务。我的假设是它的进程没有安全特权 SeCreateGlobalPrivilege。如果是这种情况,其服务元数据将仅使用其本地会话命名空间中的共享内存映射对象发布。
  5. 现在,您的客户端进程尝试在 Garmin 服务运行时启动连接... WCF 客户端通道堆栈 NetNamedPipeBinding 元素尝试根据您的服务 URL net.pipe://localhost/MyWCFConnection 为您的服务定位服务元数据. 如上面链接中所述,它将依次使用服务 URL 的各种变体执行搜索,从而为包含元数据的共享内存对象派生名称。它首先在全局命名空间中查找完整的变体列表,然后再查看本地命名空间。
  6. 在这种情况下,第一次尝试将是从“net.pipe://+/MyWCFConnection”派生的名称,并且可能无法在全局命名空间中找到具有此名称的对象。
  7. 但是,第二次尝试将基于变体“net.pipe://+/”,这将匹配在全局命名空间中发布的 Garmin 服务的共享内存映射的名称。由于搜索顺序,它永远不会到达本地会话命名空间中发布的服务元数据。
  8. 您的客户端尝试连接到 Garmin 服务的管道。假设 Garmin 服务实施了一些安全措施,导致您的客户端被拒绝访问拒绝(例如,它可能在其管道上设置 ACL)。结果很可能会以 EndpointNotFoundException 的形式出现。[稍后编辑:实际上,最有可能发生的事情是您的客户端实际上正在连接到 Garmin 服务,启动帧协议的前导握手,并接收到帧协议错误(http://schemas.microsoft.com/ws/ 2006/05/框架/故障/EndpointNotFound) 因为在 Via 记录中请求的 URL 与 Garmin 服务所期望的不匹配。然后绑定将断开连接并将此故障作为 EndpointNotFoundException 显示到您的客户端代码。]

你能为这个做什么?我会建议:

  • 如果上述假设或类似的东西可以得到证实,并且 Garmin 正在使用基于 net.pipe://localhost 的基本+相对寻址,那么最好让他们拥有问题:他们可以非常解决这样的问题通过将它们的基地址更改为更可能是唯一的东西来轻松地进行。
  • 您也许可以通过找到某种方式让您的服务应用程序以安全权限 SeCreateGlobalPrivilege 运行来解决它:如果不将其设为 Windows 服务或以管理员身份运行,这并不容易,但也许并非不可能。然后您的元数据也将发布在 Global 命名空间中,并且客户端的搜索将在 Garmin 之前找到它。
  • [稍后编辑]也许有一种解决方法,包括将绑定的 HostNameComparisonMode 属性设置为 Exact,并使用 localhost 的同义词作为服务 URL 的主机部分(例如 net.pipe://127.0.0.1/MyWCFConnection)。这可能会引导搜索围绕 Garmin 变体,以便您的客户有机会考虑本地会话命名空间中的名称。我不知道它会起作用,但值得一试,我想。
  • 还有一个很长的问题:贵公司与微软有产品支持关系吗?可以说这是 WCF 中的一个严重设计缺陷:如果您对此大惊小怪,您可能会让 Microsoft 为其发布一个 QFE 补丁,例如提供一个绑定属性来告诉客户端堆栈只尝试本地命名空间。
于 2013-04-13T11:04:45.197 回答
9

我找到了一种显示哪些应用程序使用的方法net.pipe(尽管不一定是哪些应用程序使用不正确)。

首先从 Sysinternals (Microsoft)下载 Handle 应用程序。附带说明:Process Explorer还允许您搜索句柄。

然后以管理员身份打开命令提示符,然后运行Handle.exe net.pipe(减引号)。net.pipe这将列出当前正在运行的所有应用程序。从那里,你可以一次杀死或禁用一个,直到你的罪魁祸首被发现。我几乎从来没有超过 4-5 个进程使用它。如果您未能以管理员身份运行命令提示符,它可能会给出零或仅不相关的结果。

以下是我发现干扰的所有应用程序net.pipe

  • “HP Support Solutions Framework Service” - 仅部分版本受到影响

  • “Garmin 核心更新服务” - 在较新版本中已修复,但开箱即用已损坏

  • “WBE 服务” - 由几台戴尔笔记本电脑与无线扩展坞一起使用

  • “Intel(R) Security Assist”服务 - 我在 2016 年初在几台 Win10 笔记本电脑上看到过。

  • “梭子鱼 WSA 服务” - 网络安全代理。如果您禁用此功能,可能会使客户不高兴。

  • “DropboxOEM.exe” - Dropbox 的变体,用于包含在商店购买的 PC 中。目前只在Win10上注意到。这是独一无二的,因为据我所知,它是我发现的第一个不是 Windows 服务的服务。

  • “MTC 服务” - 安装在某些 Getac 品牌 PC 上。不确定它的作用。

  • “pcdrcui.exe” - 不是服务,而是以管理员身份运行。戴尔 SupportAssist 的组件。

  • “Mitchell1/Shopkey SE Con​​nection”或“ShopHubService”或“Mitchel1/Shopkey 数据备份服务” ——数据同步服务。不确定它的作用。

  • Procore 驱动器(Procore DriveService.exe)。用途net.pipe://+/

     Procore DriveService.exe pid: 4204   type: Section        43C: \BaseNamedObjects\net.pipe:EbmV0LnBpcGU6Ly8rLw==
    
  • Keynetix.Cloud.Launcher.Service.exe。用途net.pipe://+/

     Keynetix.Cloud.Launcher.Service.exe pid: 5524   type: Section        4B8: \BaseNamedObjects\net.pipe:EbmV0LnBpcGU6Ly8rLw==
    
  • RevitAccelerator.exe(Autodesk Revit 的一部分)。这只会在安装 Revit 后立即提升。此外,此问题已在 Autodesk Revit 2020 中修复。

  • SE.Scada.Asb.InTouchDataService.exeWonderware InTouch HMI 系统附带的Wonderware InTouch IData Service ( )

  • WKSSTrayNotification.exe(不是服务,而是 ADDISON 软件的托盘应用程序部分)

软件制造商 DATEV在这里有另一个德文列表存档)。

我支持需要 的应用程序net.pipe,因此当我找到更多执行此操作的服务时,我将更新此列表。


去除并包括net.pipe:E名称中的前导也将有助于找出罪魁祸首,因为名称的其余部分是 Base64 编码的(也在此处)。因此,\BaseNamedObjects\net.pipe:EbmV0LnBpcGU6Ly8rLw==以 PowerShell 为例,我们可以将名称解码为:

$ [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String("bmV0LnBpcGU6Ly8rLw=="))
net.pipe://+/
于 2016-02-18T17:42:27.920 回答
8

我们 Microsoft 已将问题归结为 Garmin 核心更新服务创建命名管道的方式。命名管道可以在不同的范围内创建——全局和本地。全局范围本质上是机器范围的,而本地是特定于用户的。

Garmin的应用程序是

  1. 作为系统服务运行,因此侦听命名管道服务的范围是全局的。
  2. 监听“net.pipe://localhost/”的根地址(例如,没有任何子路径/段)。
  3. 使用StrongWildcard主机名比较模式
  4. 项目 1 到 3 意味着 Garmin 的应用程序本质上是一个包罗万象的网络管道连接,它与更具体的东西不匹配。
  5. 这也意味着 Garmin 完全阻止了所有使用本地范围的侦听器

解决此问题的理想方法是更改​​ Garmin 应用程序,使其net.pipe使用更具体的 URL 注册其侦听器。

于 2013-05-08T04:02:47.860 回答