原始链接:http://www.cnblogs.com/lovecherry/archive/2005/05/24/161437.html
在很多应用中需要做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个记录啊
一步一步学Remoting之一:从简单开始
一、Remoting的优缺点?
优点:
1、能让我们进行分布式开发
2、Tcp通道的Remoting速度非常快
3、虽然是远程的,但是非常接近于本地调用对象
4、可以做到保持对象的状态
5、没有应用程序限制,可以是控制台,winform,iis,windows服务承载远程对象
缺点:
1、非标准的应用因此有平台限制
2、脱离iis的话需要有自己的安全机制
二、Remoting和Web服务的区别?
ASP.NET Web 服务基础结构通过将 SOAP 消息映射到方法调用,为 Web 服务提供了简单的 API。通过提供一种非常简单的编程模型(基于将 SOAP 消息交换映射到方法调用),它实现了此机制。ASP.NET Web 服务的客户端不需要了解用于创建它们的平台、对象模型或编程语言。而服务也不需要了解向它们发送消息的客户端。唯一的要求是:双方都要认可正在创建和使用的 SOAP 消息的格式,该格式是由使用 WSDL 和 XML 架构 (XSD) 表示的 Web 服务合约定义来定义的。
. NET Remoting 为分布式对象提供了一个基础结构。它使用既灵活又可扩展的管线向远程进程提供 .NET 的完全对象语义。ASP.NET Web 服务基于消息传递提供非常简单的编程模型,而 .NET Remoting 提供较为复杂的功能,包括支持通过值或引用传递对象、回调,以及多对象激活和生命周期管理策略等。要使用 .NET Remoting,客户端需要了解所有这些详细信息,简而言之,需要使用 .NET 建立客户端。.NET Remoting 管线还支持 SOAP 消息,但必须注意这并没有改变其对客户端的要求。如果 Remoting 端点提供 .NET 专用的对象语义,不管是否通过 SOAP,客户端必须理解它们。
三、最简单的Remoting的例子
1、远程对象:
建立类库项目:RemoteObject
using System;
namespace RemoteObject
{
public class MyObject:MarshalByRefObject
{
public int Add(int a,int b)
{
return a+b;
}
}
}
2、服务端
建立控制台项目:RemoteServer
using System;
using System.Runtime.Remoting;
namespace RemoteServer
{
class MyServer
{
[STAThread]
static void Main(string[] args)
{
RemotingConfiguration.Configure("RemoteServer.exe.config");
Console.ReadLine();
}
}
}
建立配置文件:app.config
3、客户端:
建立控制台项目:RemoteClient
using System;
namespace RemoteClient
{
class MyClient
{
[STAThread]
static void Main(string[] args)
{
RemoteObject.MyObject app = (RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
Console.WriteLine(app.Add(1,2));
Console.ReadLine();
}
}
}
建立配置文件:app.config
4、测试
在最后编译的时候会发现编译报错:
1、找不到app.Add()
2、找不到RemoteObject
这是因为客户端RemoteClient没有添加RemoteObject的引用,编译器并不知道远程对象存在哪些成员所以报错,添加引用以后vs.net会在客户端也保存一个dll,可能大家会问这样如果对远程对象的修改是不是会很麻烦?其实不麻烦,对项目编译一次vs.net会重新复制dll。
然后直接运行客户端会出现“目标主机拒绝”的异常,也说明了通道没有打开
运行服务端再运行客户端出现“找不到程序集RemoteObject”!回头想想可以发现我们并在服务端对RemoteObject添加引用,编译的时候通过是因为这个时候并没有用到远程对象,大家可能不理解运行服务端的时候也通过?这是因为没有这个时候还没有激活远程对象。理所当然,对服务端要添加引用远程对象,毕竟我们的对象是要靠远程承载的。
现在再先后运行服务端程序和客户端程序,客户端程序显示3,测试成功。
四、结束语
我们通过一个简单的例子实现了最简单的remoting,对其实质没有做任何介绍,我想通过例子入门才是最简单的。
一步一步学Remoting之四:承载方式(1)
在实际的应用中我们通常只会选择用windows服务和iis来承载远程对象。选择windows服务的原因是能自启动服务,服务器重启后不需要再去考虑启动service。选择iis的理由是我们能使用集成验证等一些iis的特性。
在msdn中可以找到相关文章:
http://www.microsoft.com/china/msdn/library/architecture/architecture/architecturetopic/BuildSucApp/BSAAsecmodsecmod29.mspx
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconRemotingExampleHostingInIIS.asp
可能大家会觉得这个过程将是一个复杂的过程,其实不然,下面说一下实现方法,步骤非常少。
先来建立远程对象
using System;
using System.Data;
using System.Data.SqlClient;
namespace RemoteObject
{
public class MyObject:MarshalByRefObject
{
public DataSet GetData()
{
SqlConnection conn=new SqlConnection(System.Configuration.ConfigurationSettings.AppSettings["strconn"]);
SqlDataAdapter da=new SqlDataAdapter("select * from UBI_ProvinceMaster",conn);
DataSet ds=new DataSet();
da.Fill(ds);
return ds;
}
}
}
客户端仍然是一个控制台来进行测试:
RemoteObject.MyObject app = (RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
DataTable dt=app.GetData().Tables[0];
foreach(DataRow dr in dt.Rows)
{
Console.WriteLine(dr["iPrMId"]+" "+dr["vPrMName"]);
}
Console.ReadLine();
服务端配置文件:
运行程序,我们得到的是一个省市的列表:
一、windows服务承载
用vs.net制作一个windows服务的过程基本不超过10个步骤,所以我们不需要害怕。
1、建立一个新的windows服务项目RemoteServer1
2、打开Service1代码视图,找到OnStart部分,加入代码 System.Runtime.Remoting.RemotingConfiguration.Configure(AppDomain.CurrentDomain.BaseDirectory + "RemoteServer1.exe.config"); (不要遗漏AppDomain.CurrentDomain.BaseDirectory + )
config和控制台方式的config是一样的,我们让这个windows服务做的仅仅是从config文件读出配置信息进行配置通道。别忘记添加配置文件。
3、切换到设计视图,右键-添加安装程序
4、切换到新生成的ProjectInstaller.cs设计视图,找到serviceProcessInstaller1对Account属性设置为LocalSystem,对serviceInstaller1的ServiceName属性设置为RemoteServer1(服务的名字),StartType属性设置为Automatic(系统启动的时候自动启动服务)
5、别忘记对添加RemoteObject的引用
6、建立一个新的安装项目RemoteServerSetup(我们为刚才那个服务建立一个安装项目)
7、右键-添加-项目输出-主输出-选择RemoteService1-确定
8、右键-视图-自定义操作-自定义操作上右键-添加自定义操作-打开应用程序文件夹-选择刚才那个主输出-确定
9、重新生成这个安装项目-右键-安装
10、在服务管理器中(我的电脑-右键-管理-服务和应用程序-服务)找到RemoteServer1服务,启动服务
现在就可以打开客户端测试了!
一些FAQ:
1、启动服务的时候系统说了类似“服务什么都没有做,服务已经被停止”表示什么?
表示windows服务出错了,一般是服务的程序有问题,检查服务做了什么?在我们这个程序中仅仅添加了一行代码,一般不会出现这个错误。
2、运行客户端出现“服务器无响应”?
先检查windows服务配置文件是不是正确设置了激活方式和激活对象,客户端服务端端口号是否统一?
3、运行客户端出现“无法找到程序集”?
检查windows服务配置文件是否正确配置了激活对象的类型和uri?服务是否添加了远程对象引用?
4、远程对象类中有用到System.Configuration.ConfigurationSettings.AppSettings["strconn"],但是远程对象并没有配置文件,它从哪里读取这个config的?
因为远程对象不是独立存在的,它是被windows服务承载的,因此它从windows服务的配置文件中读取一些配置信息,远程对象本生不需要配置文件。
5、安装的时候是不是要卸载服务?
不需要,安装程序会 停止服务端-》卸载服务-》安装服务
6、在正式使用的时候怎么部署我们的系统?
如果客户端是程序仅仅只要把安装项目下面3个文件传到服务器进行安装,配置好config文件(比如连接字符串),开启服务即可。如果客户端是网站,同样把服务在服务器安装,配置好config文件(比如连接字符串),开启服务,最后把网站传到web服务器(可能和service不是同一个服务器)。
7、部署的时候需要传远程对象dll吗?
不需要,可以看到安装项目中已经自动存在了这个dll。
8、这样的系统有什么特点?
一个web服务器,多个service服务器,多个sqlservice服务器,web服务器负担比较小,所有的逻辑代码都分布到不同的service服务器上面。
最后说一个测试的tip:
如果我们远程调用对象进行测试程序非常麻烦,我们需要这么做
修改了远程对象-》重新编译安装程序-》在自己机器重新安装服务-》启动服务-》查看结果
其实可以这么做:
1、修改远程对象中的连接数据库字符串,由于不是远程对象了,我们必须从本地读取连接字符串,比如上列我们直接修改为:
SqlConnection conn=new SqlConnection("server=(local);uid=sa;pwd=;database=UBISOFT");
2、修改客户端代码,直接实例化远程对象
//RemoteObject.MyObject app = (RemoteObject.MyObject)Activator.GetObject(typeof(RemoteObject.MyObject),System.Configuration.ConfigurationSettings.AppSettings["ServiceURL"]);
RemoteObject.MyObject app = new RemoteObject.MyObject();
等到正式部署的时候我们还原数据库连接字符串从config文件中读取,还原远程对象从远程读取即可。
如果对windows服务还不是很清楚,请看以下文章:
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vbcon/html/vbwlkwalkthroughcreatingwindowsserviceapplication.asp
http://www.cnblogs.com/lovecherry/archive/2005/03/25/125527.html