Ansel's Blog

It would probably render the application more complex

博客园 首页 新随笔 联系 订阅 管理
  81 Posts :: 1 Stories :: 114 Comments :: 2 Trackbacks

用Visual C#创建Windows服务程序
作者:王凯明 发文时间:2003.05.08 10:04:39

一.Windows服务介绍:


  Windows服务以前被称作NT服务,是一些运行在Windows NT、Windows 2000和Windows XP等操作系统下用户环境以外的程序。在以前,编写Windows服务程序需要程序员很强的C或C++功底。然而现在在Visual Studio.Net下,你可以运用C++或Visual C#或Visual Basic.Net很轻松的创建一个Windows服务程序。同样,你还可以运用其他任何与CLR相容的语言来创建Windows服务程序。本文就向大家介绍如何运用Visual C#来一步一步创建一个文件监视的Windows服务程序,然后介绍如何安装、测试和调试该Windows服务程序。

在介绍如何创建Windows服务程序以前,我先向大家介绍一些有关Windows服务的背景知识。一个Windows服务程序是在Windows操作系统下能完成特定功能的可执行的应用程序。Windows服务程序虽然是可执行的,但是它不像一般的可执行文件通过双击就能开始运行了,它必须有特定的启动方式。这些启动方式包括了自动启动和手动启动两种。对于自动启动的Windows服务程序,它们在Windows启动或是重启之后用户登录之前就开始执行了。只要你将相应的Windows服务程序注册到服务控制管理器(Service Control Manager)中,并将其启动类别设为自动启动就行了。而对于手动启动的Windows服务程序,你可以通过命令行工具的NET START 命令来启动它,或是通过控制面板中管理工具下的服务一项来启动相应的Windows服务程序(见图1)。同样,一个Windows服务程序也不能像一般的应用程序那样被终止。因为Windows服务程序一般是没有用户界面的,所以你也要通过命令行工具或是下面图中的工具来停止它,或是在系统关闭时使得Windows服务程序自动停止。因为Windows服务程序没有用户界面,所以基于用户界面的API函数对其是没有多大的意义。为了能使一个Windows服务程序能够正常并有效的在系统环境下工作,程序员必须实现一系列的方法来完成其服务功能。Windows服务程序的应用范围很广,典型的Windows服务程序包含了硬件控制、应用程序监视、系统级应用、诊断、报告、Web和文件系统服务等功能。

  图1



  二.创建Windows服务程序:

在介绍如何创建Windows服务程序以前,我先向大家介绍一下.Net框架下与Windows服务相关的命名空间和其中的类库。.Net框架大大地简化了Windows服务程序的创建和控制过程,这要归功于其命名空间中的功能强大的类库。和Windows服务程序相关的命名空间涉及到以下两个:System.ServiceProcess和System.Diagnostics。

要创建一个最基本的Windows服务程序,我们只需要运用.Net框架下的System.ServiceProcess命名空间以及其中的四个类:ServiceBase、ServiceInstaller、ServiceProcessInstaller以及ServiceController,其体系结构可见图2。

  图2



  其中ServiceBase类定义了一些可被其子类重载的函数,通过这些重载的函数,服务控制管理器就可以控制该Windows服务程序了。这些函数包括:OnStart()、OnStop()、OnPause()以及OnContinue()等四个。而且ServiceBase类的子类还可以重载OnCustomCommand()函数来完成一些特定的操作。通过重载以上的一些函数,我们就完成了一个Windows服务程序的基本框架,这些函数的重载方法如下:

protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
protected override void OnPause()
{
}
protected override void OnContinue()
{
}


  ServiceBase类还为我们提供了一些属性,而这些属性是任何Widnows服务程序所必须的。其中的ServiceName属性指定了Windows服务的名称,通过该名称系统就可以调用Windows服务了,同时其它应用程序也可以通过该名称来调用它的服务。而CanPauseAndContinue和CanStop属性顾名思义就是允许暂停并恢复和允许停止的意思。

  要使得一个Windows服务程序能够正常运行,我们需要像创建一般应用程序那样为它创建一个程序的入口点。在Windows服务程序中,我们也是在Main()函数中完成这个操作的。首先我们在Main()函数中创建一个Windows服务的实例,该实例应该是ServiceBase类的某个子类的对象,然后我们调用由基类ServiceBase类定义的一个Run()方法。然而Run()方法并不就开始了Windows服务程序,我们必须通过前面提到的服务控制管理器调用特定的控制功能来完成Windows服务程序的启动,也就是要等到该对象的OnStart()方法被调用时服务才真正开始运行。如果你想在一个Windows服务程序中同时启动多个服务,那么只要在Main()函数中定义多个ServiceBae类的子类的实例对象就可以了,方法就是创建一个ServiceBase类的数组对象,使得其中的每个对象对应于某个我们已预先定义好的服务。

{
System.ServiceProcess.ServiceBase[] MyServices;
MyServices = new System.ServiceProcess.ServiceBase[] { new Service1(), new Service2() };
System.ServiceProcess.ServiceBase.Run(MyServices);
}


static void Main()

  三.添加文件监视服务:

  了解了Windows服务的基本体系结构和创建方法后,我们就可以试着往服务中添加一些实际的功能了。下面我将向大家介绍一个能监视本地文件系统的文件监视服务-FileMonitorService。该服务能根据预先设定的本地目录路径监视其中的文件包括子文件夹中的任何变化:文件创建、文件删除、文件改名、文件修改。同时,该服务还为每种变化创建了一个相对应的计数器,计数器的作用就是反映该种变化的频度。

  首先,我们打开Visual Studio.Net,新建一个Visual C#的Windows服务的项目,如图3所示:

  图3



  在重载Windows服务的OnStart()函数之前,我们先给其类添加一些计数器对象,这些计数器分别对应了文件的创建、删除、改名以及修改等变化。一旦指定目录中的文件发生以上的某种变化,与其相对应的计数器就会自动加1。所有的这些计数器都是定义为PerformanceCounter类型的变量的,该类是包含在System.Diagnostics命名空间中的。

private System.Diagnostics.PerformanceCounter fileCreateCounter;
private System.Diagnostics.PerformanceCounter fileDeleteCounter;
private System.Diagnostics.PerformanceCounter fileRenameCounter;
private System.Diagnostics.PerformanceCounter fileChangeCounter;


  之后我们便在类的InitializeComponent()方法中创建以上定义的各个计数器对象并确定其相关属性。同时我们将该Windows服务的名称设置为“FileMonitorService”,设定其即是允许暂停并恢复的又是允许停止的。

private void InitializeComponent()
              {
                     this.components = new System.ComponentModel.Container();
                     this.fileChangeCounter = new System.Diagnostics.PerformanceCounter();
                     this.fileDeleteCounter = new System.Diagnostics.PerformanceCounter();
                     this.fileRenameCounter = new System.Diagnostics.PerformanceCounter();
                     this.fileCreateCounter = new System.Diagnostics.PerformanceCounter();

                     fileChangeCounter.CategoryName = "File Monitor Service";
                     fileDeleteCounter.CategoryName = "File Monitor Service";
                     fileRenameCounter.CategoryName = "File Monitor Service";
                     fileCreateCounter.CategoryName = "File Monitor Service";

                     fileChangeCounter.CounterName = "Files Changed";
                     fileDeleteCounter.CounterName = "Files Deleted";
                     fileRenameCounter.CounterName = "Files Renamed";
                     fileCreateCounter.CounterName = "Files Created";

                     this.ServiceName = "FileMonitorService";
                     this.CanPauseAndContinue = true;
                     this.CanStop = true;
                     servicePaused = false;
              }


  接着就是重载OnStart()函数和OnStop()函数,OnStart()函数完成了一些必要的初始化工作。在.Net框架下,文件的监视功能可以由FileSystemWatcher类来完成,该类是包含在System.IO命名空间下的。该Windows服务所要完成的功能包括了监视文件的创建、删除、改名和修改等变化,而FileSystemWatcher类包含所有了对应于这些变化的处理函数。

protected override void OnStart(string[] args)
              {     
                     FileSystemWatcher curWatcher = new FileSystemWatcher();

                     curWatcher.BeginInit();
                     curWatcher.IncludeSubdirectories = true;
                     curWatcher.Path =
             System.Configuration.ConfigurationSettings.AppSettings
               ["FileMonitorDirectory"];
                     curWatcher.Changed += new FileSystemEventHandler(OnFileChanged);
                     curWatcher.Created += new FileSystemEventHandler(OnFileCreated);
                     curWatcher.Deleted += new FileSystemEventHandler(OnFileDeleted);
                     curWatcher.Renamed += new RenamedEventHandler(OnFileRenamed);
                     curWatcher.EnableRaisingEvents = true;
                     curWatcher.EndInit();
              }


  注意其中被监视的目录是存放在一个应用程序配置文件中的,该文件是一个XML类型的文件。这种做法的好处就是我们不必重新编译并发布该Windows服务而只要直接修改其配置文件就可以达到更改所要监视的目录的功能了。

  当该Windows服务启动后,一旦被监视的目录中的文件发生某种变化,与其相对应的计数器的值便会相应的增加,方法很简单,只要调用计数器对象的IncrementBy()即可。

private void OnFileChanged(Object source, FileSystemEventArgs e)
              {
                     if( servicePaused == false )
                     {
                            fileChangeCounter.IncrementBy(1);
                     }
              }
 
              private void OnFileRenamed(Object source, RenamedEventArgs e)
              {
                     if( servicePaused == false )
                     {
                            fileRenameCounter.IncrementBy(1);
                     }
              }

	      private void OnFileCreated(Object source, FileSystemEventArgs e)
              {
                     if( servicePaused == false )
                     {
                            fileCreateCounter.IncrementBy(1);
                     }
              }

	      private void OnFileDeleted(Object source, FileSystemEventArgs e)
              {
                     if( servicePaused == false )
                     {
                            fileDeleteCounter.IncrementBy(1);
                     }
              }


  OnStop()函数即是停止Windows服务的,在该Windows服务中,服务一旦停止,所有的计数器的值都应归零,但是计数器并不提供一个Reset()方法,所以我们只好将计数器中的值减去当前值来达到这个目的。

protected override void OnStop()
              {
                     if( fileChangeCounter.RawValue != 0 )
                     {
                            fileChangeCounter.IncrementBy(-fileChangeCounter.RawValue);
                     }
                     if( fileDeleteCounter.RawValue != 0 )
                     {
                            fileDeleteCounter.IncrementBy(-fileDeleteCounter.RawValue);
                     }
                     if( fileRenameCounter.RawValue != 0 )
                     {
                            fileRenameCounter.IncrementBy(-fileRenameCounter.RawValue);      
                     }
                     if( fileCreateCounter.RawValue != 0 )
                     {
                            fileCreateCounter.IncrementBy(-fileCreateCounter.RawValue);
                     }
              }


  同时,因为我们的Windows服务是允许暂停并恢复的,所以我们还得重载OnPause()函数和OnContinue()函数,方法很简单,只要设定前面定义的布尔值servicePaused即可。

protected override void OnPause()
              {
                     servicePaused = true;
              }

             protected override void OnContinue()
              {
                     servicePaused = false;
             }


  这样,该Windows服务的主体部分已经完成了,不过它并不有用,我们还必须为其添加安装文件。安装文件为Windows服务的正确安装做好了工作,它包括了一个Windows服务的安装类,该类是重System.Configuration.Install.Installer继承过来的。安装类中包括了Windows服务运行所需的帐号信息,用户名、密码信息以及Windows服务的名称,启动方式等信息。

[RunInstaller(true)]
       public class Installer1 : System.Configuration.Install.Installer
       {
              /// <summary>
              /// 必需的设计器变量。
              /// </summary>
              private System.ComponentModel.Container components = null;
              private System.ServiceProcess.ServiceProcessInstaller spInstaller;
              private System.ServiceProcess.ServiceInstaller sInstaller;

              public Installer1()
              {
                     // 该调用是设计器所必需的。
                     InitializeComponent();

                    // TODO: 在 InitComponent 调用后添加任何初始化
              }

              #region Component Designer generated code
              /// <summary>
              /// 设计器支持所需的方法 - 不要使用代码编辑器修改
              /// 此方法的内容。
              /// </summary>
             private void InitializeComponent()
              {
                     components = new System.ComponentModel.Container();

                     // 创建ServiceProcessInstaller对象和ServiceInstaller对象
                     this.spInstaller = 
              new System.ServiceProcess.ServiceProcessInstaller();
                     this.sInstaller = new System.ServiceProcess.ServiceInstaller();

                     // 设定ServiceProcessInstaller对象的帐号、用户名和密码等信息
                     this.spInstaller.Account = 
              System.ServiceProcess.ServiceAccount.LocalSystem;
                     this.spInstaller.Username = null;
                     this.spInstaller.Password = null;

		     // 设定服务名称
                     this.sInstaller.ServiceName = "FileMonitorService";

		     // 设定服务的启动方式
                     this.sInstaller.StartType = 
              System.ServiceProcess.ServiceStartMode.Automatic;

                     this.Installers.AddRange(
              new System.Configuration.Install.Installer[] 
                {this.spInstaller, this.sInstaller });
              }
              #endregion
       }


  同样,因为该Windows服务中运用到了计数器对象,我们也要为其添加相应的安装文件,安装文件的内容和作用与前面的类似。限于篇幅,这里就不给出相应的代码了,有兴趣的读者可以参考文后附带的源代码文件。

  到此为止,整个Windows服务已经构建完毕,不过Windows服务程序和一般的应用程序不同,它不能直接调试运行。如果你直接在IDE下试图调试运行之,就会报出如图4所示提示。

  图4



  根据其中提示,我们知道安装Windows服务需要用到一个名为InstallUtil.exe的命令行工具。而运用该工具安装Windows服务的方法是非常简单的,安装该Windows服务的命令如下:

installutil FileMonitorService.exe


  而要卸载该Windows服务,你只要输入如下的命令即可:

installutil /u FileMonitorService.exe


  Windows服务安装成功后,它便会出现在服务控制管理器中,如图5所示。

  图5



  这样,该文件监视的Windows服务就完成了,一旦我们对被监视的目录中的文件进行操作,相应的计数器就会运作,起到监视文件变化的作用。不过这个功能对于一般的用户而言没多大意义,然而你可以在此基础上添加新的功能,比如构建一个后台的文件处理系统,一旦被监视的目录中的文件发生某种变化,Windows服务便对其进行特定的操作,而最终用户就不必去关心后台处理程序是如何实现的了。

  四.总结:

  本文向大家介绍了Windows服务的一些基本概念和构建一般的Windows服务所需的方法,同时还向大家展示了一个具有文件监视功能的Windows服务程序。通过本文,读者应该能体会到构建Windows服务并不是想象中的那么复杂,这主要还得归功于.Net框架为我们所作的大量努力。同时,希望大家能在本文给出的实例的基础上构建更加完善和更加强大的Windows服务程序。最后希望本文对大家能有不少帮助。

  (注:源代码文件为Source.rar
posted on 2005-08-22 11:08 Ansel 阅读(2119) 评论(4)  编辑 收藏 网摘 所属分类: C#学习笔记

Feedback

#1楼 [楼主] 2005-08-22 14:43 Ansel      
转贴:用C#创建Windows服务(Windows Services)
Windows服务在Visual Studio 以前的版本中叫NT服务,在VS.net启用了新的名称。用Visual C# 创建Windows服务不是一件困难的事,本文就将指导你一步一步创建一个Windows服务并使用它。这个服务在启动和停止时,向一个文本文件中写入一些文字信息。

第一步:创建服务框架
要创建一个新的 Windows 服务,可以从Visual C# 工程中选取 Windows 服务(Windows Service)选项,给工程一个新文件名,然后点击 确定。

你可以看到,向导向工程文件中增加WebService1.cs类:

如下图来设置属性:


其中各属性的含意是:
 Autolog 是否自动写入系统的日志文件
 CanHandlePowerEvent 服务时候接受电源事件
 CanPauseAndContinue 服务是否接受暂停或继续运行的请求
 CanShutdown 服务是否在运行它的计算机关闭时收到通知,以便能够调用 OnShutDown 过程
 CanStop 服务是否接受停止运行的请求
 ServiceName 服务名

第二步:向服务中增加功能
在 .cs代码文件中我们可以看到,有两个被忽略的函数 OnStart和OnStop。

OnStart函数在启动服务时执行,OnStop函数在停止服务时执行。在这里,当启动和停止服务时,向一个文本文件中写入一些文字信息,代码如下:
protected override void OnStart(string[] args)
{
FileStream fs = new FileStream(@"d:\mcWindowsService.txt" , FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter m_streamWriter = new StreamWriter(fs);
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine("mcWindowsService: Service Started"+DateTime.Now.ToString()+"\n");
m_streamWriter.Flush();
m_streamWriter.Close();
fs.Close();

}

protected override void OnStop()
{
FileStream fs = new FileStream(@"d:\mcWindowsService.txt" , FileMode.OpenOrCreate, FileAccess.Write);
StreamWriter m_streamWriter = new StreamWriter(fs);
m_streamWriter.BaseStream.Seek(0, SeekOrigin.End);
m_streamWriter.WriteLine(" mcWindowsService: Service Stopped "+DateTime.Now.ToString()+"\n");
m_streamWriter.Flush();
m_streamWriter.Close();
fs.Close();
}

第三步: 将安装程序添加到服务应用程序

Visual Studio.NET 随附有安装组件,可用来安装与服务应用程序相关联的资源。安装组件在正在安装到的系统上注册一项单个的服务,并使服务控制管理器知道该服务的存在。
要正确安装服务,并不需要在安装程序中进行任何特殊编码。但是,如果需要向安装进程添加特殊功能,则可能偶尔需要修改安装程序的内容。
将安装程序添加到服务应用程序的步骤是:
1:在解决方案中,访问要向其中添加安装组件的服务的Design视图。
2:在属性窗口中,单击添加安装程序链接
这时项目中就添加了一个新类 ProjectInstaller 和两个安装组件 ServiceProcessInstaller 和 ServiceInstaller,并且服务的属性值被复制到组件。
3:若要确定如何启动服务,请单击 ServiceInstaller 组件并将 StartType 属性设置为适当的值。
 Manual 服务安装后,必须手动启动。
 Automatic 每次计算机重新启动时,服务都会自动启动。
 Disabled 服务无法启动。
4:将serviceProcessInstaller类的Account属性改为 LocalSystem
这样,不论是以哪个用户登录的系统,服务总会启动。

第四步:生成服务程序
通过从生成菜单中选择生成来生成项目。
注意 不要通过按 F5 键来运行项目——不能以这种方式运行服务项目。
第五步:安装服务
1. 访问项目中的已编译可执行文件所在的目录。
2. 用项目的输出作为参数,从命令行运行 InstallUtil.exe。在命令行中输入下列代码:
installutil yourproject.exe
卸载服务
用项目的输出作为参数,从命令行运行 InstallUtil.exe。
installutil /u yourproject.exe


至此,整个服务已经编写,编译,安装完成,你可以在控制面板的管理工具的服务中,看到你编写的服务。
来自:csdn


  回复  引用  查看    

#2楼 [楼主] 2005-08-22 14:53 Ansel      
利用vs.net快速开发windows服务(c#)

在很多应用中需要做windows服务来操作数据库等操作,比如
(1)一些非常慢的数据库操作,不想一次性去做,想慢慢的通过服务定时去做,比如定时为数据库备份等
(2)在.net Remoting中利用windows服务来做Host

利用vs.net我们可以在几分钟之内建立其windows服务,非常简单

下面说一下步骤
1. 新建一个项目
2. 从一个可用的项目模板列表当中选择Windows服务
3. 设计器会以设计模式打开
4. 从工具箱的组件表当中拖动一个Timer对象到这个设计表面上 (注意: 要确保是从组件列表而不是从Windows窗体列表当中使用Timer)
5. 设置Timer属性,Interval属性200毫秒(1秒进行5次数据库操作)
6. 然后为这个服务填加功能
7.双击这个Timer,然后在里面写一些数据库操作的代码,比如
SqlConnection conn=new SqlConnection("server=127.0.0.1;database=test;uid=sa;pwd=275280");
SqlCommand comm=-new SqlCommand("insert into tb1 ('111',11)",conn);
conn.Open();
comm.ExecuteNonQuery();
conn.Close();
8. 将这个服务程序切换到设计视图
9. 右击设计视图选择“添加安装程序”
10. 切换到刚被添加的ProjectInstaller的设计视图
11. 设置serviceInstaller1组件的属性:
1) ServiceName = My Sample Service
2) StartType = Automatic (开机自动运行)
12. 设置serviceProcessInstaller1组件的属性 Account = LocalSystem
13. 改变路径到你项目所在的bin\Debug文件夹位置(如果你以Release模式编译则在bin\Release文件夹)
14. 执行命令“InstallUtil.exe MyWindowsService.exe”注册这个服务,使它建立一个合适的注册项。(InstallUtil这个程序在WINDOWS文件夹\Microsoft.NET\Framework\v1.1.4322下面)
15. 右击桌面上“我的电脑”,选择“管理”就可以打计算机管理控制台
16. 在“服务和应用程序”里面的“服务”部分里,你可以发现你的Windows服务已经包含在服务列表当中了
17. 右击你的服务选择启动就可以启动你的服务了
看看数据库是不是一秒多了5个记录啊

需要注意的是:
如果你修改了这个服务,路径没有变化的话是不需要重新注册服务的,如果路径发生了变化,需要先卸载这个服务InstallUtil.exe /u参数,然后再重新安装这个服务,不能直接安装。还有就是windows服务是没有界面的,不要企图用控制的输出方式来输出一些信息,你只能添加一个EventLog,通过WriteEntry()来写日志。

关于怎么用windows服务来做一个远程服务可以看一下http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetHT15.asp

  回复  引用  查看    

#3楼 [楼主] 2005-08-22 14:59 Ansel      
Building Secure ASP.NET Applications: Authentication, Authorization, and Secure Communication



How To: Host a Remote Object in a Windows Service
J.D. Meier, Alex Mackman, Michael Dunner, and Srinath Vasireddy
Microsoft Corporation

November 2002

Microsoft® ASP.NET
Microsoft Visual Studio® .NET
Microsoft Windows® 2000

See the Landing Page for a starting point and complete overview of Building Secure ASP.NET Applications.

Summary: Objects called using the .NET Remoting infrastructure can be hosted by ASP.NET, custom executables or Windows services. This How To shows you how to host a remote object in a Windows service and call it from an ASP.NET Web application. (7 printed pages)

Contents
Notes
Requirements
Summary
References

This How To describes how to host a remote object in a Windows service and call it from an ASP.NET Web application.

Notes
Remote objects (that is, .NET objects accessed remotely using .NET Remoting technology) can be hosted in Windows services, custom executables, or ASP.NET.
Clients communicate with remote objects hosted in custom executables or Windows services by using the TCP channel.
Clients communicate with remote objects hosted in ASP.NET by using the HTTP channel.
If security is the prime concern, host objects in ASP.NET and use the HTTP channel. This allows you to benefit from the underlying security features of ASP.NET and IIS.
For information about how to host a remote object in ASP.NET (with IIS), see article Q312107, "HOW TO: Host a Remote Object in Microsoft Internet Information Services."
If performance is the prime concern, host objects in a Windows service and use the TCP channel. This option provides no built-in security.
Requirements
The following items describe the recommended hardware, software, network infrastructure, skills and knowledge, and service packs you will need.

Microsoft® Windows® 2000 operating system
Microsoft Visual Studio® .NET development system
The procedures in this article also require that you have knowledge of the Microsoft Visual C#™ development tool.

Summary
This How To includes the following procedures.

Create the Remote Object Class
Create a Windows Service Host Application
Create a Windows Account to Run the Service
Install the Windows Service
Create a Test Client Application
1. Create the Remote Object Class
This procedure creates a simple remote object class. It provides a single method called Add that will add two numbers together and return the result.

To create the remote object class

Start Visual Studio .NET and create a new Visual C# Class Library project called RemoteObject.
Use Solution Explorer to rename class1.cs as Calculator.cs.
In Calculator.cs, rename Class1 as Calculator and rename the default constructor accordingly.
Derive the Calculator class from MarshalByRefObject to make the class remotable.
public class Calculator : MarshalByRefObject

Add the following public method to the Calculator class.
public int Add( int operand1, int operand2 )
{
return operand1 + operand2;
}

On the Build menu, click Build Solution.
2. Create a Windows Service Host Application
This procedure creates a Windows service application, which will be used to host the remote object. When the service is started it will configure the TCP remoting channel to listen for client requests.

Note This procedure uses an Installer class and the Installutil.exe command line utility to install the Windows service. To uninstall the service, run Installutil.exe with the /u switch. As an alternative, you could use a Setup and Deployment Project to help install and uninstall the Windows service.
To create a Windows Service host application

Add a new Visual C# Windows Service project called RemotingHost to the current solution.
Use Solution Explorer to rename Service1.cs as RemotingHost.cs.
In RemotingHost.cs, rename the Service1 class as HostService and rename the default constructor accordingly.
At the top of the file, add the following using statement beneath the existing using statements.
using System.Runtime.Remoting;

Locate the Main method and replace the existing line of code that initializes the ServicesToRun variable with the following.
ServicesToRun = new System.ServiceProcess.ServiceBase[] {
new HostService() };

Locate the InitializeComponent method and set the ServiceName property to RemotingHost.
this.ServiceName = "RemotingHost";

Locate the OnStart method and add the following line of code to configure remoting. The fully qualified path to the configuration file will be passed as a start parameter to the service.
RemotingConfiguration.Configure(args[0]);

Add a new C# class file to the project and name it HostServiceInstaller.
Add an assembly reference to the System.Configuration.Install.dll assembly.
Add the following using statements to the top of HostServiceInstaller beneath the existing using statement.
using System.ComponentModel;
using System.ServiceProcess;
using System.Configuration.Install;

Derive the HostServiceInstaller class from the Installer class.
public class HostServiceInstaller : Installer

Add the RunInstaller attribute at the class level as follows.
[RunInstaller(true)]
public class HostServiceInstaller : Installer

Add the following two private member variables to the HostServiceInstaller class. The objects will be used when installing the service.
private ServiceInstaller HostInstaller;
private ServiceProcessInstaller HostProcessInstaller;

Add the following code to the constructor of the HostServiceInstaller class.
HostInstaller = new ServiceInstaller();
HostInstaller.StartType =
System.ServiceProcess.ServiceStartMode.Manual;
HostInstaller.ServiceName = "RemotingHost";
HostInstaller.DisplayName = "Calculator Host Service";
Installers.Add (HostInstaller);
HostProcessInstaller = new ServiceProcessInstaller();
HostProcessInstaller.Account = ServiceAccount.User;
Installers.Add (HostProcessInstaller);

Within Solution Explorer, right-click RemotingHost, point to Add, and then click Add New Item.
In the Templates list, click Text File and name the file app.config.
Configuration files with the name app.config are automatically copied by Visual Studio .NET as part of the build process to the output folder (for example, <projectdir>\bin\debug) and renamed as <applicationname>.config.

Click OK to add the new configuration file.
Add the following configuration elements to the new configuration file.
<configuration>
<system.runtime.remoting>
<application name="RemoteHostService">
<service>
<wellknown type="RemoteObject.Calculator, RemoteObject"
objectUri="RemoteObject.Calculator"
mode="Singleton" />
</service>
<channels>
<channel ref="tcp" port="8085">
<serverProviders>
<formatter ref="binary" />
</serverProviders>
</channel>
</channels>
</application>
</system.runtime.remoting>
</configuration>

On the Build menu, click Build Solution.
3. Create a Windows Account to Run the Service
This procedure creates a Windows account used to run the Windows service.

To create a Windows account to run the service

Create a new local user account called RemotingAccount. Enter a password and select the Password never expires check box.
In the Administrative Tools programs group, click Local Security Policy.
Use the Local Security Policy tool to give the new account the Log on as a service privilege.
4. Install the Windows Service
This procedure installs the Windows service using the installutil.exe utility and then start the service.

To install the Windows service

Open a command window and change directory to the Bin\Debug directory beneath the RemotingHost project folder.
Run the installutil.exe utility to install the service.
installutil.exe remotinghost.exe

In the Set Service Login dialog box, enter the user name and password of the account created earlier in procedure 3 and click OK.
View the output from the installutil.exe utility and confirm that the service is installed correctly.

Copy the RemoteObject.dll assembly into the RemotingHost project output directory (that is, RemotingHost\Bin\Debug).
From the Administrative Tools program group, start the Services MMC snap-in.
In the Services list, right-click Calculator Host Service, and then click Properties.
Enter the full path to the service's configuration file (remotinghost.exe.config) into the Start parameters field.
Note A quick way to do this is to select and copy the Path to executable field and paste it into the Start parameters field. Then append the ".config" string.
Click Start to start the service.
Confirm that the service status changes to Started.
Click OK to close the Properties dialog box.
5. Create a Test Client Application
This procedure creates a test console application that is used to call the remote object within the Windows service.

To create a test client application

Add a new Visual C# Console application called RemotingClient to the current solution.
Within Solution Explorer, right-click RemotingClient, and then click Set as StartUp Project.
Add an assembly reference to the System.Runtime.Remoting.dll assembly.
Add a project reference to the RemoteObject project.
Add the following using statements to the top of class1.cs beneath the existing using statements.
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
using RemoteObject;

Add the following test code to the Main method to call and invoke the Calculator object hosted by the Windows service.
TcpChannel chan = new TcpChannel();
ChannelServices.RegisterChannel(chan);
Calculator calc = (Calculator)Activator.GetObject(
typeof(RemoteObject.Calculator),
"tcp://localhost:8085/RemoteObject.Calculator");
if (calc == null)
System.Console.WriteLine("Could not locate server");
else
Console.WriteLine("21 + 21 is : " + calc.Add(21,21) );

On the Build menu, click Build Solution.
Run the client application and confirm that the correct result is displayed in the console output window.
References
For information about how to host a remote object in ASP.NET (with IIS), see article Q312107, "HOW TO: Host a Remote Object in Microsoft Internet Information Services".



  回复  引用  查看    

#4楼  2007-06-02 11:39 敬辉      
不错,写的很细。谢谢
  回复  引用  查看    





标题  
姓名  
主页
Email (博主才能看到) 
验证码 *  看不清,换一张 [登录][注册]
内容(请不要发表任何与政治相关的内容)  
  登录  使用高级评论  新用户注册  返回页首  恢复上次提交      
Google站内搜索

China-pub 计算机图书网上专卖店!6.5万品种 2-8折!
近千种 9-95 新二手计算图书火热销售中!
开发者征途系统新作:《设计模式——基于C#的工程化实现及扩展》

相关文章:

相关链接: