首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >创建用于监视正在运行的windows服务并与之交互的用户界面。

创建用于监视正在运行的windows服务并与之交互的用户界面。
EN

Stack Overflow用户
提问于 2009-11-21 10:29:10
回答 2查看 12K关注 0票数 15

我需要在我的服务器上的windows服务中运行一堆可插入的进程,并且想要创建一个允许我与该服务使用的每个插件进行交互的用户界面。

在用户界面和长时间运行的windows服务之间进行通信最常用的方法是什么?我正在考虑提供一个介于两者之间的位置,比如数据库,并使用某种消息队列向服务发出命令。你们中有没有人实现过这样的方法,或者其他更好的方法?在此过程中,您遇到过WHat问题吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2009-11-22 02:42:02

微软表示,远程处理是一项遗留技术,所有新的分布式应用程序都应该使用进行开发。有关更多详细信息,请参阅here

Windows Communication Foundation是两个.NET进程相互通信的推荐方式。WCF提供了统一的编程模型,通过抽象与特定通信机制(例如,套接字、管道等)相关的许多复杂性,大大简化了分布式开发。

鉴于您的详细情况,我建议将每个Windows服务插件都设置为WCF服务。对于每个WCF服务,即插件,定义它需要向您的UI公开的接口。该接口只是一个用ServiceContract属性装饰的C#接口。此接口包含方法,每个方法都使用OperationContract属性进行装饰,您的UI将使用这些方法与WCF服务(插件)进行通信。这些方法可以接受和返回任何可序列化的.NET类型,也可以接受和返回您自己的自定义类型。要在WCF中使用自定义类型,只需用DataContract属性修饰它们,并用DataMember属性标记要通过WCF交换的成员。

定义好ServiceContract接口后,定义一个实现该接口的类。每个OperationContract方法做它需要做的任何事情,例如,与数据库交互,计算一些值,等等。下面是一个简短但有效的示例:

代码语言:javascript
运行
AI代码解释
复制
using System.ServiceModel;
namespace AdditionServiceNamespace
{
    [DataContract]
    public class Complex
    {
        [DataMember]
        public int real;
        [DataMember]
        public int imag;
    }
    [ServiceContract]
    public interface IAdditionService
    {
        [OperationContract]
        Complex Add(Complex c1, Complex c2);
    }
    public class AdditionService : IAdditionService
    {
        public Complex Add(Complex c1, Complex c2)
        {
            Complex result = new Complex();
            result.real = c1.real + c2.real;
            result.imag = c1.imag + c2.imag;
            return result;
        }
    }
}

下一步是托管此WCF服务,以便它可供您的UI使用。由于您将使用Windows服务,因此在Windows服务的OnStart()回调中托管您的WCF服务非常容易,如下所示:

代码语言:javascript
运行
AI代码解释
复制
using System.ServiceModel;
using System.ServiceProcess;
using AdditionServiceNamespace;
namespace WindowsServiceNamespace
{
    public class WindowsService : ServiceBase
    {
        static void Main()
        {
            ServiceBase[] ServicesToRun = new ServiceBase[]
            { new WindowsService() };
            ServiceBase.Run(ServicesToRun);
        }
        private ServiceHost _host;
        public WindowsService()
        {
            InitializeComponent();
        }
        protected override void OnStart(string[] args)
        {
            _host = new ServiceHost(typeof(AdditionService));
            _host.Open();
        }
        protected override void OnStop()
        {
            try
            {
                if (_host.State != CommunicationState.Closed)
                {
                    _host.Close();
                }
            }
            catch
            {
                // handle exception somehow...log to event viewer, for example
            }
        }
    }
}

剩下的唯一要做的就是为你的Windows服务定义一个app.config文件,它将配置你的WCF服务的某些必需的方面。这可能看起来有点夸张,但请记住两件事。首先,当您将WCF服务类添加到项目中时,Visual Studio会自动为您提供一个基本的app.config文件。其次,app.config文件为您提供了对您的WCF服务的大量控制,而不需要更改代码。下面是上面示例的配套app.config文件:

代码语言:javascript
运行
AI代码解释
复制
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <services>
            <service name="AdditionServiceNamespace.MyAdditionService"
                     behaviorConfiguration="default">
                <endpoint name="AdditionService"
                     address="net.pipe://localhost/AdditionService"
                     binding="netNamedPipeBinding"
                     contract="AdditionServiceNamespace.IAdditionService" />
                <endpoint address="net.pipe://localhost/AdditionService/MEX"
                     binding="mexNamedPipeBinding"
                     contract="IMetadataExchange" />
            </service>
        </services>
        <behaviors>
            <serviceBehaviors>
                <behavior name="default">
                    <serviceMetadata />
                </behavior>
            </serviceBehaviors>
        </behaviors>
    </system.serviceModel>
</configuration>

请注意,AdditionService WCF服务有两个端点。元数据交换端点用于客户端的代码生成,因此暂时忽略它。第一个端点配置为使用NetNamedPipeBinding。如果您的UI和Windows服务将在同一台计算机上运行,则使用此绑定(有关选择要使用的适当绑定的流程图,请参阅here )。但是,如果您的UI和Windows服务将在不同的计算机上运行,则不能使用此绑定。在这种情况下,您可以使用NetTcpBinding作为替代。要用NetTcpBinding替换NetNamedPipeBinding,您只需更改端点的地址和绑定,如下所示:

代码语言:javascript
运行
AI代码解释
复制
<endpoint name="AdditionService"
          address="net.tcp://<machine hostname here>/AdditionService"
          binding="netTcpBinding"
          contract="AdditionServiceNamespace.IAdditionService" />

不需要修改代码!进行更改,重新启动您的服务,您的WCF服务现在可用于远程计算机。如果您愿意,您甚至可以允许同一WCF服务使用多个端点。关键是,app.config文件提供了极大的灵活性,而不需要更改代码。

就这样!现在,您的UI可以使用托管在Windows服务中的WCF服务。

那么UI端,即客户端,是如何工作的呢?

这就是WCF真正发挥作用的地方。开始使用WCF时,最容易做的事情就是利用Visual Studio的代码生成功能。确保您的Windows服务(托管AdditionService的服务)正在运行。在您的UI项目中,右键单击解决方案资源管理器中的项目,并选择Add Service Reference...菜单选项。在“地址”框中,键入net.pipe://localhost/AdditionService,然后单击“转到”按钮。您应该会看到AdditionService显示在服务列表中。在Namespace框中,键入AdditionService,然后单击OK按钮。

执行这些步骤将生成一个客户端代理和一个正确定义的app.config文件,它们将添加到您的UI项目中。这个客户端代理成为您的客户端AdditionService应用程序接口,您可以这样使用它:

代码语言:javascript
运行
AI代码解释
复制
using TestConsoleApp.AdditionService;
namespace TestConsoleApp
    class Program
    {
        static void Main(string[] args)
        {
            AdditionServiceClient client = new AdditionServiceClient();
            Complex c1 = new Complex(), c2 = new Complex();
            c1.real = 3; c1.imag = 5;
            c2.real = 1; c2.imag = 7;
            Complex result = client.Add(c1, c2);
        }
    }
}

注意这有多简单。基本上,实例化了一个客户端代理AdditionServiceClient。然后创建两个Complex对象。最后,调用客户端代理上的Add()方法,并返回Complex结果。

客户端代理的Add()方法实际上是将两个Complex对象传递给AdditionService服务中托管的Windows服务。AdditionService执行加法运算,然后返回结果。所有这些都是通过命名管道实现的,但是请注意,这里根本没有特定于命名管道的代码!WCF抽象了由IAdditionService接口定义的编程模型背后的所有复杂性。

我知道要消化的信息很多,但我希望WCF的强大和易用性是显而易见的。当然,这个示例只涉及WCF中所有可用内容的一小部分。

最后,WCF应该是您用来在UI和Windows服务之间进行通信的机制。有关更多信息,我强烈推荐Juval Lowy的书 For all things WCF。您也可以访问他的网站IDesign.net,获取免费的WCF代码示例。有关WCF的更多介绍,请在dnrTV上观看此free video。它介绍了WCF的用途,并通过一些简单易懂的示例演示了WCF编程。

票数 38
EN

Stack Overflow用户

发布于 2009-11-21 10:39:40

最好的方法是在IPC通道上使用.NET远程处理。

虽然这看起来很复杂,但第二次设置就相当容易了。

我建议您先试用一些示例,了解如何将远程对象从一个应用程序公开到另一个应用程序。

我以前没有使用过消息队列,所以我不能对此发表评论。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/1775124

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档