.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;
}
}
}
只需实现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;
}
}
}
相关文章推荐
- 应用框架的设计与实现——.NET平台(10 授权服务.PrincipalPermissionAttribute)
- 应用框架的设计与实现——.NET平台(2)
- 基于.Net(C#开发)平台的三层框架架构软件的设计与实现
- 应用框架的设计与实现——.NET平台(6 自定配置文件节读取类)
- 应用框架的设计与实现——.NET平台(6 源码分析)
- 应用框架的设计与实现——.NET平台(10 授权服务.源码分析)
- 应用框架的设计与实现——.NET平台(10 授权服务.CodeAccessSecurityAttribute)
- Silverlight企业应用快速开发平台框架设计(二)分析-平台实现重点是什么,要怎么做?
- 应用框架的设计与实现——.NET平台(7.事件通知服务.委托.异步编程)
- 应用框架的设计与实现——.NET平台(9 消息队列服务代码分析)
- 应用框架的设计与实现——.NET平台(8.1 Windows服务.线程)
- 应用框架的设计与实现——.NET平台(9 消息队列产品安装)
- 应用框架的设计与实现——.NET平台(1)
- 应用框架的设计与实现——.NET平台4.2代码测试问题解决
- 应用框架的设计与实现——.NET平台(7.事件通知服务.源码分析)
- 应用框架的设计与实现——.NET平台(8.2 Windows服务)
- 基于.Net(C#开发)平台的三层框架架构软件的设计与实现
- 应用框架的设计与实现——.NET平台(3)
- 应用框架的设计与实现——.NET平台(4.3 SAF代码分析)
- 应用框架的设计与实现——.NET平台(5 缓存服务.源码分析)