建立用于监测的用户接口,并与一个运行Windows服务交互 [英] Creating a user interface for monitoring and interacting with a running windows service

查看:118
本文介绍了建立用于监测的用户接口,并与一个运行Windows服务交互的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要我的服务器上运行了一堆可插拔过程的一个窗口服务,并希望创建一个用户界面,可以让我的服务,每次使用的插件进行交互。

I need to run a bunch of pluggable processes in a windows service on my server and want to create a user interface that allows me to interact with each of the plugins in use by the service.

这是一个用户界面和一个长期运行的窗口服务之间的通信的最常用方法(或方法)?我想提供一个穿针引线的位置,如数据库,并使用某种形式的消息队列中发出命令来服务的。你们中实现这样的方法,或其他一些优异的方法呢?什么问题都有,你在这个过程中遇到过?

What is the most common method (or methods) for communication between a user interface and a long-running windows service? I am thinking of providing a go-between location such as a database and using some sort of messaging queue to issue commands to the service. Have any of you implemented such an approach, or some other superior approach? WHat problems have you come across in the process?

推荐答案

不要使用远程!虽然它肯定会正常工作,微软表示,远程处理是一种传统技术和所有新的分布式应用程序应该使用WCF开发。请参见这里了解更多详情。

Windows通讯基础(WCF)是推荐的方式维持了二.NET进程相互通信。 WCF提供了一个统一的编程模型,通过抽象的许多具体的沟通机制,例如,插座,管道等相关的复杂性大大简化了分布式发展。

Windows Communication Foundation (WCF) is the recommended way for two .NET processes to communicate with each other. WCF provides a unified programming model that greatly simplifies distributed development by abstracting many of the complexities associated with specific communication mechanisms, e.g., sockets, pipes, etc.

鉴于您的情况的细节,我建议使每一个Windows服务插件的WCF服务。对于每一个WCF服务,即,插件,定义它需要暴露到您的UI的接口。该接口只是装饰用<一个一个C#接口href="http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.aspx?PHPSESSID=tn8k5...">ServiceContract属性。此接口包​​含的方法,其中的每一个装饰与<一个href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.aspx">OperationContract属性,你的用户界面将使用与WCF服务(插件)进行通信。这些方法可以接受并返回任何序列化的.NET类型或,这是常有的情况下,你自定义的类型。要使用自定义类型与WCF,只是装点他们的<一个href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datacontractattribute.aspx">DataContract属性和标记要要通过WCF与<一个交换成员href="http://msdn.microsoft.com/en-us/library/system.runtime.serialization.datamemberattribute.aspx">DataMember属性。

Given the details of your situation, I would suggest making each Windows service plugin a WCF service. For each WCF service, i.e., plugin, define the interface that it needs to expose to your UI. The interface is simply a C# interface adorned with the ServiceContract attribute. This interface contains the methods, each of which is adorned with the OperationContract attribute, that your UI will use to communicate with the WCF service (plugin). These methods can accept and return any serializable .NET type or, as is often the case, your own custom types. To use custom types with WCF, simply decorate them with the DataContract attribute and mark the members that you want to be exchanged via WCF with the DataMember attribute.

一旦你有你的<一个href="http://msdn.microsoft.com/en-us/library/system.servicemodel.servicecontractattribute.aspx?PHPSESSID=tn8k5...">ServiceContract定义的接口,定义一个实现该接口的类。每个<一href="http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.aspx">OperationContract方法做什么,它需要做的,例如,与数据库进行交互,算出一旦你做到了这一点,你已经有效地定义了一个WCF服务一定的价值,等等。这里有一个很短,但工作,例如:

Once you have your ServiceContract interface defined, define a class that implements that interface. Each OperationContract method does whatever it needs to do, e.g., interact with database, calculate some value, etc. Once you've done this, you have effectively defined a WCF service. Here's a short, but working, example:

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;
        }
    }
}

下一步是这样,它可使用您的UI来举办这次WCF服务。由于您将使用一个Windows服务,托管WCF服务做很轻松地在你的Windows服务的的OnStart()回调,像这样:

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
            }
        }
    }
}

唯一剩下要做的就是定义一个app.config文件为您的Windows服务,将配置WCF服务的某些必要的方面。这似乎有点小题大做,但要两件事。首先,Visual Studio会自动给你一个基本的app.config文件,当您添加WCF服务类项目。其次,app.config文件给你,而不需要更改code的控制权WCF服务中巨细靡遗。下面是上面的例子同伴app.config文件:

The only thing left to do is to define an app.config file for your Windows service that will configure certain required aspects of your WCF service. This may seem like overkill, but keep two things in mind. First of all, Visual Studio gives you a basic app.config file automatically when you add a WCF service class to your project. Second, the app.config file gives you a tremendous amount of control over your WCF service without requiring changes to the code. Here's the companion app.config file for the example above:

<?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服务有两个端点。元数据交换终结点是用于code代客户端,所以忽略它。第一个端点配置为使用<一个href="http://msdn.microsoft.com/en-us/library/system.servicemodel.netnamedpipebinding.aspx">NetNamedPipeBinding.这是的的结合使用,如果你的用户界面和Windows服务将在同一台机器上运行(请参阅<一href="http://stackoverflow.com/questions/1613586/c-wcf-inter-process-communication/1613601#1613601">here关于选择合适的结合使用)的流程图。但是,这种结合,如果你的用户界面和Windows服务将在不同的机器上运行,不能使用。在这种情况下,你可以使用<一个href="http://msdn.microsoft.com/en-us/library/system.servicemodel.nettcpbinding.aspx">NetTcpBinding作为替代。要替换的NetTcpBinding的为NetNamedPipeBinding,你只需要更改地址和端点的结合,是这样的:

Note that the AdditionService WCF service has two endpoints. The metadata exchange endpoint is used for code generation by the client, so ignore it for now. The first endpoint is configured to use the NetNamedPipeBinding. This is the binding to use if your UI and Windows service will be running on the same machine (see here for a flowchart on selecting the appropriate binding to use). However, this binding cannot be used if your UI and Windows service will be running on different machines. In that case, you could use the NetTcpBinding as a replacement. To substitute the NetTcpBinding for the NetNamedPipeBinding, you would simply need to change the address and binding of the endpoint, like this:

<endpoint name="AdditionService"
          address="net.tcp://<machine hostname here>/AdditionService"
          binding="netTcpBinding"
          contract="AdditionServiceNamespace.IAdditionService" />

没有code的变化是必需的!进行更改,重新启动您的服务,您的WCF服务现在可到远程机器。你甚至可以让多个端点相同的WCF服务,如果你需要的话。问题的关键是,app.config文件提供了拥有极大的灵活性,而不需要更改code。

No code changes are required! Make the change, restart your service, and your WCF service is now available to remote machines. You can even allow multiple endpoints for the same WCF service if you so desired. The point is, the app.config file offers a tremendous amount of flexibility without requiring changes to the code.

这就是它!您现在可以通过你的UI托管的Windows服务,可以使用内部的WCF服务。

That's it! You now have a WCF service hosted inside your Windows service available for use by your UI.

那么,如何在UI方面,即客户端,工作?

So how does the UI side, i.e., the client side, work?

这是WCF的真正的力量开始发挥作用。当开始变得与WCF,以最简单的办法是利用Visual Studio的code生成功能。请确保您的Windows服务(一个托管AdditionService)正在运行。在您的UI项目,在解决方案资源管理器右键单击项目,选择的添加服务引用... 的菜单选项。在地址的框中,键入 net.pipe:本地主机// / AdditionService ,然后点击开始的按钮。您应该看到AdditionService出现在服务列表中。在命名空间的框中,键入 AdditionService ,然后点击确定的按钮。

This is where the real power of WCF comes into play. When getting started with WCF, the easiest thing to do is leverage Visual Studio's code generation capabilities. Make sure that your Windows service (the one hosting the AdditionService) is running. In your UI project, right-click on your project in the Solution Explorer and select the Add Service Reference... menu option. In the Address box, type net.pipe://localhost/AdditionService, and click the Go button. You should see the AdditionService show up in the Services list. In the Namespace box, type AdditionService and click the OK button.

执行这些步骤将生成一个客户端代理,并已添加到您的UI项目中的正确定义app.config文件。该客户端代理成为您的客户端AdditionService API,并且使用这样的:

Performing these steps will generate a client proxy and a properly defined app.config file that are added to your UI project. This client proxy becomes your client-side AdditionService API, and you use it like this:

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 ,被实例化。然后,两个复合对象的创建。最后,添加()上的客户端代理方法被调用,而复合返回结果。

Notice how simple this is. Basically, a client proxy, AdditionServiceClient, is instantiated. Then two Complex objects are created. Finally, the Add() method on the client proxy is invoked, and a Complex result is returned.

这是怎么回事幕后是,添加()客户端代理实际上是传递方法的两个复合对象托管在Windows服务的AdditionService WCF服务。所述AdditionService执行加法,然后返回结果。所有这一切都发生在一个命名管道,但是的的通知没有命名管道的具体code在这里了!的WCF已经提取了这一切背后的编程模型的复杂性是由定义IAdditionService接口。

What is going on behind the scenes is that the Add() method of the client proxy is actually passing the two Complex objects to the AdditionService WCF service hosted in the Windows service. The AdditionService performs the addition and then returns the result. All of this happens over a named pipe, but notice that there is no named pipe-specific code here at all! WCF has abstracted all of that complexity behind a programming model that is defined by the IAdditionService interface.

我知道这是一个大量的信息来消化,但我希望这是显而易见的是多么的强大和易于使用的WCF即可。当然,这个例子仅命中一切的一小部分即内的WCF可用

I know this is a lot of information to digest, but I hope it is evident just how powerful and easy-to-use WCF can be. Of course, this example only hits a small subset of everything that is available within WCF.

在最后,虽然,WCF应该是你用你的UI和您的Windows服务之间进行通信的机制。欲了解更多信息,我会强烈建议Juval洛伊的书编程WCF服务万物WCF。您也可以访问他的网站, IDesign.net ,免费WCF code样本。欲了解更多介绍WCF,看这个免费影片在dnrTV。它涵盖WCF的目的,并通过一些容易遵循的例子演示了WCF编程。

In the end, though, WCF should be the mechanism you use to communicate between your UI and your Windows service. For more information, I would highly recommend Juval Lowy's book Programming WCF Services for all things WCF. You can also visit his website, IDesign.net, for free WCF code samples. For more introduction to WCF, watch this free video at dnrTV. It covers the purpose of WCF and demonstrates WCF programming through some easy-to-follow examples.

这篇关于建立用于监测的用户接口,并与一个运行Windows服务交互的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆