本章的目的是实现一个 Windows服务 的通用框架程序,使用该框架,windows服务开发者不需了解开发 windows服务的细节,
只需实现IService接口,将编译生成的dll文件名、服务类全路径名写在配置文件内,就可以实现windows服务功能的加载和启动。
1.IService
2.配置文件
3.Windows服务通用框架程序
这一部分主要有3个类:
Service1:windows服务通用框架类;
SecuritySwitchThread:单个服务组建的用户账号切换类;
ProjectInstaller:vs.net生成的,用来安装 windows服务的类。
Service1
SecuritySwitchThread
只需实现IService接口,将编译生成的dll文件名、服务类全路径名写在配置文件内,就可以实现windows服务功能的加载和启动。
1.IService
public
interface
IService
{
void Start(); // windows 服务启动时会以线程的方式调用这个方法;需要实现什么功能就写这里吧
void Stop(); // windows 服务关闭时会调用这个方法;有什么需要释放的资源,保存的数据就在这里写吧
void Initialize(XmlNode configXml); // 对象初始化的方法,在Start()方法前执行,参数是定义在配置文件中的xml节点
}
{
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 >
< 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
}
}
}
}
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;
}
}
}
/// 用来切换运行用户身份的类
/// </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;
}
}
}