CWF框架之windowsService
我们在做应用的的时候经常会遇到定时运行或者端口监视等,这样我们需要开发一个程序长时间的运行并且随操作系统启动。
这个时候最佳选择我觉得上windows服务。当然在.net上开发一个服务上一件那么轻松的事情,但是会发现一个问题,在系统中
往往需要多个服务或者不可预知的情况给予扩展,这个时候需要重新编译开发完成的服务,然后卸载先前的服务,再安装最新的。
可能开始几个服务还不觉得怎么样,随着系统的升级和功能的健全重构是要命的,如果不卸载先前的服务重新安装新服务造成系统
资源的浪费也非常不划算,在统一管理上启动和停止服务也是个头痛的事情。
那么这里就采用了陈新老师的解决方案,把本身就上windows服务的服务做成一个可扩展的框架然后通过配置去扩展系统需要用到的服务
这样每次扩展就不需要重新卸载安装甚至不用重新编译程序,并且实现统一的启动停止操作。
按照我写博客的习惯基本不会有多少介绍,因为现在上上班时间。。。
那就继续看代码。
using System;
using System.Collections.Generic;
using System.Text;
using System.Xml;
namespace CWF.WindowsService
{
/// <summary>
/// Windows服务接口,每个自定义windows服务必须继承于该接口
/// </summary>
interface IWindowsService
{
/// <summary>
/// 启动服务
/// </summary>
void ServiceStart();
/// <summary>
/// 停止服务
/// </summary>
void ServiceStop();
/// <summary>
///
/// </summary>
/// <param name="ConfigNode"></param>
void Intializd(XmlNode ConfigNode);
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
using System.Threading;
using System.Collections;
using System.Configuration;
using CWF.ConfigManager;
using CWF.DocumentService;
namespace CWF.WindowsService
{
/// <summary>
/// Windows服务框架
/// 开发者:欧阳寒玟
/// 开发时间:2009-01-18
/// 个人网页:www.coldwin.org
/// </summary>
public partial class WindowsService : ServiceBase
{
private IDocumentServer<string> log;
public WindowsService()
{
log = ServerSession.log;
log.CreateAuthor = "WindowsService->";
log.SafeLevel = 3;
InitializeComponent();
}
/// <summary>
/// 声明一个hashtable保存服务对象的启动线程
/// </summary>
private Hashtable ServiceTable=new Hashtable();
/// <summary>
/// 启动所有服务
/// </summary>
/// <param name="args"></param>
protected override void OnStart(string[] args)
{
try
{
ConfigManager.ConfigManager configmanager = (ConfigManager.ConfigManager)ConfigurationManager.GetSection("Framework");
ConfigManager.WinServiceConfig winServices = configmanager.getWinService();
List<object> services = winServices.getIServers();
foreach (IServerObj serobj in services)
{
try
{
Thread thread = new Thread(new ThreadStart(((IWindowsService)serobj.Service).ServiceStart));
thread.Priority = ThreadPriority.Lowest;
ServiceTable.Add(serobj.Service, thread);
thread.Start();
}
catch (Exception ex)
{
log.Save(log.CreateAuthor + "OnStart->try-2",ex.Message);
}
}
}
catch(Exception ex)
{
log.Save(log.CreateAuthor + "OnStart->try-1", ex.Message);
}
}
/// <summary>
/// 关闭所有服务
/// </summary>
protected override void OnStop()
{
if (ServiceTable.Count > 0)
{
try
{
foreach (object service in ServiceTable.Keys)
{
try
{
((IWindowsService)service).ServiceStop();
}
catch
{
}
}
foreach (object obj in ServiceTable.Values)
{
Thread th = (Thread)obj;
if (th.IsAlive)
{
try
{
th.Abort();
}
catch (Exception ex)
{
log.Save(log.CreateAuthor + "OnStart->try-1", ex.Message);
}
}
}
Thread.Sleep(1000);
}
catch (Exception ex)
{
log.Save(log.CreateAuthor + "OnStart->try-1", ex.Message);
}
}
}
}
}
这样就OK了,是不是很简单,简单适用就好。那么每次需要服务就去app.config读取OK了。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="Framework" type="CWF.ConfigManager.ConfigManagerHander,CWF.ConfigManager"/>
</configSections>
<connectionStrings>
<add name="sql" connectionString="Data Source=(local);Initial Catalog=PliceProtectSystem;Persist Security Info=True;User ID=sa;Password=123" providerName="System.Data.SqlClient"/>
</connectionStrings>
<!-- 框架自定义配置处理节点 -->
<Framework name="CWF" vison="2.015" Developer="ouyanghanwen">
<!-- 类工厂服务 -->
<classFactory name="CWF.ClassFactory">
<classGroup name="CWF.AbstractDB">
<!--<class name="SQLH" type="CWF.DataHelper.SQLH,CWF.DataHelper" message="针对于SQL数据库的数据处理" url="tcp://61.147.112.61:8899/SQLH"/>-->
<class name="SQLH" type="CWF.DataHelper.SQLH,CWF.DataHelper" message="针对于SQL数据库的数据处理"/>
<class name="AccessH" type="CWF.DataHelper.AccessH,CWF.DataHelper" message="针对于access数据库的数据处理"/>
<class name="OracleH" type="CWF.DataHelper.OracleH,CWF.DataHelper" message="针对于Oracle数据库的数据处理" />
<class name="AbstractDB" type="CWF.DataHelper.AbstractDB,CWF.DataHelper" message="提供的数据处理基类,可以继承他写自己的数据处理类" />
</classGroup>
<classGroup name="CWF.OtherDataHelper">
<class name="ParamList" type="CWF.DataHelper.ParamList,CWF.DataHelper" message="数据处理中的参数列表类,专门为数据出具提供相关参数列表" />
<class name="SimpleProce" type="CWF.DataHelper.SimpleProce,CWF.DataHelper" message="一个简单数据库处理类,实现基本的数据处理方法" />
<class name="DataHelpFactory" type="CWF.DataHelper.DataHelpFactory,CWF.DataHelper" message="采用类工厂创建一个类" />
</classGroup>
</classFactory>
<!-- 消息队列服务 -->
<messageQueuey name="CWF.MessageQueuey">
<sendMessage>
<ipGroup>
<ip name="ProductMessage" adress="tcp:192.168.1.158/private$/ProductMessage/" message="设备故障维护的消息队列"/>
<ip name="ProductDataProce" adress="tcp:192.168.1.158/private$/ProductMessage/" message="消息反馈的消息队列"/>
</ipGroup>
</sendMessage>
<receveMessage>
<ipGroup>
<ip name="ProductMessage" adress="tcp:192.168.1.158/private$/ProductMessage/" message="设备故障维护的消息队列"/>
<ip name="ProductDataProce" adress="tcp:192.168.1.158/private$/ProductMessage/" message="消息反馈的消息队列"/>
</ipGroup>
</receveMessage>
</messageQueuey>
<!--Windows 服务-->
<windowsSercice>
<service name="DBHelp" type="CWF.WindowsService.BDService,CWF.WindowsService" message="数据处理服务">
<userDoman></userDoman>
<userName>欧阳寒玟</userName>
<userPwd></userPwd>
</service>
</windowsSercice>
</Framework>
</configuration>
这里提供一个简单的实例
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using System.Threading;
namespace CWF.WindowsService
{
/// <summary>
/// 数据处理的windows服务
/// 开发者:欧阳寒玟
/// 开发时间:2010-03-22
/// 修改时间:2010-03-22
/// 联系 Q Q:332123660
/// </summary>
/// <remarks></remarks>
class BDService:IWindowsService
{
private Thread thread;
#region IWindowsService 成员
/// <summary>
/// 启动服务
/// </summary>
/// <remarks></remarks>
public void ServiceStart()
{
thread = new Thread(new ThreadStart(Start));
thread.Start();
}
/// <summary>
/// 停止服务
/// </summary>
/// <remarks></remarks>
public void ServiceStop()
{
if (thread.IsAlive)
{
thread.Abort();
}
}
/// <summary>
///
/// </summary>
/// <param name="ConfigNode"></param>
public void Intializd(System.Xml.XmlNode ConfigNode)
{
throw new NotImplementedException();
}
#endregion
/// <summary>
/// 服务主程序
/// </summary>
/// <remarks></remarks>
private void Start()
{
TcpChannel tcpchannel = new TcpChannel(8899);
ChannelServices.RegisterChannel(tcpchannel,true);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(CWF.DataHelper.IDbHelper), "DBH", WellKnownObjectMode.SingleCall);
}
}
}
OK 文字少请见谅,欢迎讨论。