C# 创建用于监视运行的windows服务并与之交互的用户界面

C# 创建用于监视运行的windows服务并与之交互的用户界面,c#,.net,.net-3.5,windows-services,C#,.net,.net 3.5,Windows Services,我需要在我的服务器上的windows服务中运行一系列可插入进程,并希望创建一个用户界面,允许我与服务使用的每个插件进行交互 用户界面和长期运行的windows服务之间最常用的通信方法是什么?我正在考虑提供一个中间位置,如数据库,并使用某种消息队列向服务发出命令。你们中有谁实施过这样的方法,或者其他更好的方法吗?您在这个过程中遇到了什么问题?您最好通过IPC通道使用.NET远程处理 虽然安装起来似乎很复杂,但第二次安装却相当容易 我建议您在将远程对象从一个应用程序公开到另一个应用程序时,首先使用几

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


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

您最好通过IPC通道使用.NET远程处理

虽然安装起来似乎很复杂,但第二次安装却相当容易

我建议您在将远程对象从一个应用程序公开到另一个应用程序时,首先使用几个示例

我以前没有使用过消息队列,因此无法对此发表评论。

不要使用远程处理虽然远程处理肯定会奏效,但微软表示远程处理是一项遗留技术,所有新的分布式应用程序都应该使用WCF开发。有关更多详细信息,请参阅

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

考虑到您的具体情况,我建议将每个Windows服务插件都设置为WCF服务。对于每个WCF服务,即插件,定义它需要向您的UI公开的接口。该接口只是一个用属性修饰的C#接口。此接口包含方法,每个方法都带有属性,UI将使用这些方法与WCF服务(插件)通信。这些方法可以接受和返回任何可序列化的.NET类型,或者像通常情况一样,您自己的自定义类型。要在WCF中使用自定义类型,只需使用属性装饰它们,并使用属性标记希望通过WCF交换的成员

定义接口后,定义一个实现该接口的类。每个方法都做它需要做的任何事情,例如,与数据库交互,计算一些值,等等。一旦您这样做了,您就有效地定义了WCF服务。下面是一个简短但有效的示例:

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服务非常容易,如下所示:

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文件:

<?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>
注意这是多么简单。基本上,客户端代理,
AdditionServiceClient
,是实例化的。然后创建两个
复杂的
对象。最后,调用客户机代理上的
Add()
方法,并返回一个
Complex
结果

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

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


不过,最终,WCF应该是您用来在UI和Windows服务之间进行通信的机制。要了解更多信息,我强烈推荐尤瓦尔·洛伊(Juval Lowy)的《一切事物WCF》一书。你也可以访问他的网站,免费获取WCF代码示例。有关WCF的更多介绍,请在dnrTV观看。它涵盖了WCF的用途,并通过一些简单易懂的示例演示了WCF编程。

远程处理实际上已被弃用-自托管WCF服务将是当代的等效服务,配置可能与此类似。远程处理不再是推荐的方法;WCF是@马特:谢谢。这似乎是错误的。对于IPC IMO,远程处理比WCF容易得多。感谢您的详细回复!这就是我喜欢这个网站的原因:非常感谢。在研究Java应用程序的“windows服务包装器/适配器”时碰巧发现了这一点;正在考虑购买昂贵的现成包装(适用于任何java应用程序)。。。阅读这篇信息丰富的回复,最好的方法是:掸掉Visual Studio和C护目镜上的灰尘:-)
<endpoint name="AdditionService"
          address="net.tcp://<machine hostname here>/AdditionService"
          binding="netTcpBinding"
          contract="AdditionServiceNamespace.IAdditionService" />
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);
        }
    }
}