转载: C#高级编程:安装程序
切换到Visual Studio .NET的设计视图,从上下文菜单中选择Add Installer选项,可以给服务添加安装程序。使用Add Installer选项时,将创建一个新的ProjectInstaller类、一个ServiceInstaller实例和一个ServiceProcessInstaller实例。
图32-11显示的是服务的安装程序类。
图 32-11
根据这张图表,下面详细讨论由Add Installer选项创建的ProjectInstaller.cs文件中的源代码。
1. 安装程序类
ProjectInstaller类是从System.Configuration.Install.Installer派生出来的,它是所有定制安装程序类的基类。使用Installer类,可以创建基于事务的安装。使用基于事务的安装时,如果安装失败了,系统还可以回滚到以前的状态,安装程序所做的所有修改都会被取消。如图32-11所示,Installer类中有Install()、Commit()、Rollback()和Uninstall()方法,这些方法都是从安装程序中调用的。
如果RunInstaller属性的值为true,则在安装程序集时就会调用ProjectInstaller类。定制的安装程序和installutil.exe(这个程序以后将用到)都能检查该属性。
using System;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
namespace Wrox.ProCSharp.WinServices
{
///
/// Summary description for ProjectInstaller.
///
[RunInstaller(true)]
public class ProjectInstaller : System.Configuration.Install.Installer
{
2. ServiceProcessInstaller类和ServiceInstaller类
与Windows Forms应用程序类似,InitializeComponent()是在ProjectInstaller类的构造函数中调用的。在InitializeComponent()中,创建了ServiceProcessInstaller类和ServiceInstaller类的实例。这两个类都是从ComponentInstaller类中派生出来的,ComponentInstaller类本身派生于Installer。
从ComponentInstaller中派生出来的类可以用作安装进程的一个部分。记住,一个服务进程可以包括多个服务。ServiceProcessInstaller类用于配置进程,为这个进程中所有服务定义值,而ServiceInstaller类用于服务的配置,因此,每个服务都需要ServiceInstaller类的一个实例。如果进程中有3个服务,则必须添加额外的ServiceInstaller对象,也就是说,在这种情况下,需要3个ServiceInstaller实例:
private System.ServiceProcess.ServiceProcessInstaller
serviceProcessInstaller1;
private System.ServiceProcess.ServiceInstaller serviceInstaller1;
///
/// Required designer variable.
///
private System.ComponentModel.Container components = null;
public ProjectInstaller()
{
// This call is required by the Designer.
InitializeComponent();
// TODO: Add any initialization after the InitComponent call
}
///
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
///
private void InitializeComponent()
{
this.serviceProcessInstaller1 =
new System.ServiceProcess.ServiceProcessInstaller();
this.serviceInstaller1 =
new System.ServiceProcess.ServiceInstaller();
//
// serviceProcessInstaller1
//
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
//
// serviceInstaller1
//
this.serviceInstaller1.ServiceName = "QuoteService";
//
// ProjectInstaller
//
this.Installers.AddRange(
new System.Configuration.Install.Installer[]
{this.serviceProcessInstaller1,
this.serviceInstaller1});
}
}
}
ServiceProcessInstaller安装一个执行ServiceBase类的可执行文件。ServiceProcessInstaller类包含用于整个进程的属性。在进程中所有服务共享的属性如表32-1所示。
表 32-1
属 性
|
描 述
|
Username,
Password
|
如果Accout属性设置为ServiceAccout.User,则Username属性和Password属性指出服务是在哪一个账户下运行
|
Account
|
使用这个属性,可以指定服务的账户类型
|
HelpText
|
HelpText是只读属性,它返回的文本用于帮助设置用户名和密码
|
用于运行服务的进程可以用ServiceProcessInstaller类的Accout属性指定,其值可以是ServiceAccout枚举的任一值,如表32-2所示。
表 32-2
值
|
意 义
|
LocalSystem
|
设置这个值可以指定服务在本地系统上使用有高度权限的用户账户,但这个账户允许匿名用户进入网络,因此它没有网络上的权限
|
LocalService
|
这个账户类型给任意远程服务器提供计算机的证书
|
NetworkService
|
类似于LocalService,这个值指定把计算机的证书传送给远程服务器,但与LocalService不同,这种服务可以以非授权用户的身份登录本地系统。顾名思义,这个账户只能用于需要从网络上获得资源的服务
|
User
|
把Accout属性设置为ServiceAccout.User,表示可以指定应在服务中使用的账户
|
ServiceInstaller是每一个服务都需要的类,这个类的属性可以用于进程中的每一个服务,其属性有StartType、DisplayName、ServiceName和ServicesDependedOn,如表32-3所示。
表 32-3
属 性
|
说 明
|
|
StartType
|
StartType 指出服务是手动启动还是自动启动。它的值可以是:ServiceStartMode.Automatic
ServiceStartMode.Manual
ServiceStartMode.Disabled。
如果使用ServiceStartMode.Disabled,服务就不能启动。这个选项可用于不应在系统中启动的服务。例如,如果没有得到需要的硬件控制器,就可以把该选项设置为Disabled
|
|
DisplayName
|
DisplayName 是显示给用户的服务的友好名称。此外,这个名称也用于控制和监视服务的管理工具
|
|
ServiceName
|
ServiceName是服务的名称。这个值必须与服务程序中ServiceBase类的ServiceName属性一致,这个名称与把ServiceInstaller配置为需要的服务程序相关
|
|
ServicesDependentOn
|
指定必须在服务启动之前启动的一个服务组。当服务启动时,所有相依存的服务都自动启动,并且我们的服务也将启动
|
提示:
如果在ServiceBase的派生类中改变了服务的名称,还必须修改ServiceInstaller对象中Service Name属性的值。
注意:
在测试阶段,最好把StartType的值设置为Manual。如果服务因程序中的错误不能停止,仍可以重新启动系统。如果把StartType的值设置为Automatic,服务就会在重新启动系统时自动启动!当确信没有问题时,可以在以后改变这个配置。
3. ServiceInstallerDialog类
System.ServiceProcess.Design命名空间中的另一个安装类是ServiceInstallerDialog。在安装过程中,如果希望系统管理员输入用户名和密码,就可以使用这个类。
如果ServiceProcessInstaller类的Account属性设置为ServiceAccount.User,Username和Password属性设置为null,则在安装时,图32-12所示的Set Service Login对话框将自动显示出来。此时,也可以取消安装。
图 32-12
4. installutil
在把安装类添加到项目中之后,就可以使用installutil.exe实用程序安装和卸载服务了。这个实用程序可以用于安装包含Installer类的所有程序集。installutil.exe实用程序调用派生于Installer类的方法Installer()进行安装,调用UnInstaller()方法进行卸载。
安装和卸载服务的命令分别是:
installutil quoteservice.exe
installutil /u quoteservice.exe
注意:
如果安装失败了,一定要检查安装日志文件InstallUtil.InstallLog和. InstallLog。通常,在安装日志文件中可以发现一些非常有用的信息,例如:“The specified service already exists”。
5. 客户
在成功地安装服务后,就可以从Services MMC中手动启动服务(详细内容请参阅32.5节),并启动客户应用程序,图32-13显示了访问服务的客户。
图 32-13