2

我有一个稍微复杂的设置,当然,在 XP 中可以正常工作,但在 Windows 7 上会卡住。这可能看起来很疯狂,但在当时是有道理的!

我有一个 WPF 应用程序,它启动然后启动另一个与外部设备通信的应用程序。启动后,它通过命名管道 (net.pipe) 使用 WCF(由新进程托管)与新进程建立通信。这似乎在任一操作系统上都可以正常工作。

我想让 WPF 应用程序的一些功能在外部对命令行程序可用,所以我设置了另一个 WCF 服务,这次由 WPF 应用程序托管,并再次通过命名管道公开它。同样,这似乎有效。

接下来,我想让 WPF 应用程序的功能通过 Web 可用。现在,重要的是 WPF 应用程序可以从普通用户帐户运行,所以我认为在 Windows 7 上完成这项工作的最佳方法是创建一个 Windows 服务,该服务将提供 Web 服务部分并让它与WPF 应用程序通过与命令行正常工作的相同命名管道。我实现了这一点,它在 XP 上运行良好,但在 Windows 7 上运行良好。问题似乎在于试图在 Windows 服务和 WPF 应用程序之间建立命名管道连接。

如果我以管理员身份运行 WPF 应用程序,它工作正常。因此,运行 Windows 服务的帐户似乎存在问题,无法与通过命名管道托管 WCF 服务的常规用户帐户进行通信。有没有办法使这项工作?似乎在普通用户帐户中运行的 WCF 服务可以使用命名管道与在同一帐户中运行的另一个应用程序进行通信,但它似乎不能用不同的帐户做同样的事情。

奇怪的是,反过来似乎也奏效了。事实上,windows 服务确实也公开了一个带有命名管道绑定的服务(它被用作激活函数,因为该服务一直在运行)。我可以毫无问题地从 WPF 应用程序连接到该服务。

我的安全知识有些有限。任何人都可以了解正在发生的事情吗?

4

2 回答 2

3

这个问题之前在 SO 上已经被问过好几次了。例如,请参阅通过命名管道从 Windows 服务连接到桌面应用程序

问题是您的用户会话应用程序不具备允许他们在其他会话可见的全局内核命名空间中创建对象所需的 SeCreateGlobalPrivilege 安全权限,但只能在仅在会话中可见的本地命名空间中创建对象。另一方面,默认情况下使用此权限运行的服务可以这样做。

不是命名管道对象本身以这种方式被约束到本地命名空间,而是另一个命名内核对象,一个共享内存部分,WCF命名管道绑定依赖于它,以便向其客户端发布实际名称管道,这是一个 GUID,每次启动服务时都会更改。

您可以通过颠倒角色来绕过此限制 - 使 Windows 服务应用程序成为您的用户会话应用程序连接到的 WCF 服务。Windows 服务将其服务发布到您的会话没有问题。以这种方式连接起来更有意义,因为 Windows 服务始终在运行,而您的会话及其应用程序在您登录和注销时来来去去。您将希望使用双工合同定义服务,以便一旦建立连接,通过 WCF 服务的基本通信流仍然可以按照您最初预期的方向发生。

于 2012-04-26T23:11:54.630 回答
2

应用程序(WPF/Console)正在创建本地范围的命名管道(默认情况下,当它们无法创建全局范围的管道时会发生这种情况)。我的猜测是它们可以相互通信,因为它们可以看到彼此命名的管道,因为它们在同一个帐户下运行。

Windows 服务具有更高的权限,因此可以创建一个全局范围的命名管道供客户端应用程序查看。

您可以查看Christian Weyer 博客上的讨论。

于 2012-04-24T15:25:04.540 回答