您的位置:首页 > 其它

.NET平台应用框架设计与实现

2007-11-04 11:23 330 查看
本章的目的是实现一个 Windows服务 的通用框架程序,使用该框架,windows服务开发者不需了解开发 windows服务的细节,
只需实现IService接口,将编译生成的dll文件名、服务类全路径名写在配置文件内,就可以实现windows服务功能的加载和启动。

1.IService


public interface IService




...{


void Start(); // windows 服务启动时会以线程的方式调用这个方法;需要实现什么功能就写这里吧


void Stop(); // windows 服务关闭时会调用这个方法;有什么需要释放的资源,保存的数据就在这里写吧


void Initialize(XmlNode configXml); // 对象初始化的方法,在Start()方法前执行,参数是定义在配置文件中的xml节点


}



2.配置文件


<configuration>


<configSections>


<section name="Framework" type="SAF.Configuration.ConfigurationHandler,SAF.Configuration" />


<section name="MyApplication" type="SAF.Configuration.ConfigurationHandler,SAF.Configuration" />


</configSections>


<Framework type="SAF.Configuration.ConfigurationManager,SAF.Configuration">


<!-- windows服务 的配置节点 -->


<SAF.WindowsService>


<!-- 一个 windows服务 的例子 -->


<Service name="empty" type="SAF.WindowsService.EmptyService,SAF.WindowsService">


<!-- 用户可自行定义的节点(1个或者多个) -->


<File>C: empEmptyService.txt</File>


<!-- 运行用户的配置信息 -->


<RunAs InheritIdentity="false">


<Domain>AVANADE-C006T6X</Domain>


<User>user1</User>


<Password>password</Password>


</RunAs>


</Service>


</SAF.WindowsService>


</Framework>


</configuration>

3.Windows服务通用框架程序

这一部分主要有3个类:
Service1:windows服务通用框架类;
SecuritySwitchThread:单个服务组建的用户账号切换类;
ProjectInstaller:vs.net生成的,用来安装 windows服务的类。

Service1


// 继承自ServiceBase才能被windows识别为windows服务的实现


public class Service1 : System.ServiceProcess.ServiceBase




...{




/**//// <summary>


/// Required designer variable.


/// </summary>


private ArrayList threadArray = new ArrayList(); // 单个windows服务所在的线程池


private ArrayList instanceArray = new ArrayList(); // windows服务对象池


private System.ComponentModel.Container components = null;




public Service1()




...{


InitializeComponent();


}




// vs.net自动生成的代码


// 进程中可以运行的用户服务是Service1,可以添加其它的


static void Main()




...{


System.ServiceProcess.ServiceBase[] ServicesToRun;




ServicesToRun = new System.ServiceProcess.ServiceBase[] ...{ new Service1() };


System.ServiceProcess.ServiceBase.Run(ServicesToRun);


}






/**//// <summary>


/// Required method for Designer support - do not modify


/// the contents of this method with the code editor.


/// </summary>


private void InitializeComponent()




...{


components = new System.ComponentModel.Container();


this.ServiceName = "SAF.WindowsService";


}






/**//// <summary>


/// Clean up any resources being used.


/// </summary>


protected override void Dispose( bool disposing )




...{


if( disposing )




...{


if (components != null)




...{


components.Dispose();


}


}


base.Dispose( disposing );


}






/**//// <summary>


/// windows服务启动时要执行的方法


/// </summary>


protected override void OnStart(string[] args)




...{


// 取得配置文件中windows服务节点的信息


ConfigurationManager cm = (ConfigurationManager)ConfigurationSettings.GetConfig("Framework");


SAF.Configuration.ServiceConfiguration serviceConfig = cm.ServiceConfig;


XmlNode servicesXml = serviceConfig.ServicesXml;




// 遍历windows服务节点的子节点


foreach (XmlNode node in servicesXml.ChildNodes)




...{


try




...{


string typeInfo;


// 建立windows服务对象


typeInfo =node.Attributes["type"].Value;


Type type = Type.GetType(typeInfo);


IService instance = (IService)Activator.CreateInstance(type);




// 初始化windows服务对象


instance.Initialize(node);


XmlNode runAs = node.SelectSingleNode("RunAs");


instanceArray.Add(instance);




// 使用SecuritySwitchThread 对象处理windows服务对象


ThreadStart ts = new ThreadStart(instance.Start);


SecuritySwitchThread sst = new SecuritySwitchThread(ts,runAs);


// windows服务开始执行


sst.Start();


threadArray.Add(sst.BaseThread);


}


catch (Exception ex)




...{


//write to the event log


}


}


}






/**//// <summary>


/// delegate used when invoke the OnStop method asynchronous during service shut down.


/// </summary>


public delegate void OnStopDelegate();






/**//// <summary>


/// windows服务停止时要执行的方法


/// </summary>


protected override void OnStop()




...{


foreach (object o in instanceArray)




...{


try




...{


IService service = (IService)o;




if (service !=null)




...{


//invoke the delegate asynchronous to stop each started service.


OnStopDelegate osd = new OnStopDelegate(service.Stop);


osd.BeginInvoke(null,null); // 异步方式通知服务类结束运行


}


}


catch (Exception ex)




...{


//write to the event log


}


}




// 给出5秒钟的时间,等待服务完成结束操作


Thread.Sleep(5000);


foreach (object o in threadArray)




...{


try




...{


Thread t = (Thread)o;




if (t !=null)




...{


// 如果线程还在运行状态,那么强制结束它


if (t.IsAlive == true)




...{


t.Abort();


}


}


}


catch (Exception ex)




...{


//write to the event log


}


}


}


}

SecuritySwitchThread




/**//// <summary>


/// 用来切换运行用户身份的类


/// </summary>


public class SecuritySwitchThread




...{


private ThreadStart serviceDelegate;


private XmlNode runAs;


private Thread newT;






/**//// <summary>


/// 接受一个委托和一个xml节点作为参数


/// </summary>


/// <param name="start">the ThreadStart delegate for the target method</param>


/// <param name="xml">the configuraiton data contains the user account information</param>


public SecuritySwitchThread (ThreadStart start, XmlNode xml)




...{


serviceDelegate = start;


runAs = xml;


// create a new thread that calls the WrappingMethod


newT = new Thread(new ThreadStart(WrappingMethod));


}




public void Start()




...{


newT.Start();


}






/**//// <summary>


/// 包装后的方法


/// </summary>


private void WrappingMethod()




...{


// 切换当前使用的用户账号


bool inheritIdentity = Boolean.Parse(runAs.Attributes["InheritIdentity"].Value);




if (inheritIdentity == false)




...{


string userid = runAs.SelectSingleNode("User").InnerText;


string password= runAs.SelectSingleNode("Password").InnerText;


string domain = runAs.SelectSingleNode("Domain").InnerText;


//call the utility class to switch the current thread's security context.


SecurityUtility su = new SecurityUtility(); // SAF.Utility.SecurityUtility 前面提到过的切换用户的方法


su.Switch(userid, password,domain);


}




// 实际开始执行线程


serviceDelegate();


}






/**//// <summary>


/// 实际在运行的线程对象


/// </summary>


public Thread BaseThread




...{


get




...{


return newT;


}


}


}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐