安装部署的问题
没有做过安装盘,因为一直做的都是项目,现场开发比较多,所以基本都是做的文件复制,而且是做的ASP.NET开发,所以部署更简单了,只要复制文件然后修改一下数据库配置就可以了。不过由于一个客户比较认真(他也认为直接复制更简单、方便),再加上市场上需要发布,所以就做了一个安装盘。
想找一下现成的安装工具,比较好的要花钱,免费的效果又不好,而且做Web的发布相对简单,也不想去花钱买安装工具。有人说VS.NET的安装部署方案太简单,不好用。但由于是集成的,我们决定还是用VS.NET做安装盘。
安装程序的具体工作就是:把程序复制到硬盘,然后在安装目录上创建虚拟目录,创建对应的数据库并配置。由于数据库允许重新创建、安装、配置,所以把程序安装和数据库安装分开了。前面的工作VS.NET的部署都能非常容易的完成,但创建虚拟目录需要自己处理了。
也很简单,就是需要创建一个安装类库,继承自System.Configuration.Install.Installer,然后就可以自己处理的。下面是一个代码片断:
using System;
using System.Xml;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using Microsoft.Win32;
using System.IO;
namespace MyInstall
{
/// <summary>
/// CreateDirVirtual 的摘要说明。
/// </summary>
[RunInstaller(true)]
public class CreateDirVirtual : System.Configuration.Install.Installer
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// 安装状态保存用的,也可以不定义做为参数传递给相应的方法
/// </summary>
private System.Collections.IDictionary state = null ;
public CreateDirVirtual()
{
// 该调用是设计器所必需的。
InitializeComponent();
// TODO: 在 InitComponent 调用后添加任何初始化
}
/// <summary>
/// 安装,即安装程序时会调用这个方法
/// </summary>
/// <param name="stateSaver"></param>
public override void Install(System.Collections.IDictionary stateSaver)
{
//保存安装信息
state = stateSaver ;
base.Install(stateSaver);
//创建虚拟目录的方法
this.Createvir();
}
/// <summary>
/// 卸载,当卸载程序时调用的方法
/// </summary>
/// <param name="savedState"></param>
public override void Uninstall(IDictionary savedState)
{
//保存状态。需要注意的是:安装和卸载时并不在一个进程中,所以savedState并不相同
state = savedState ;
base.Uninstall (savedState);
//删除虚拟目录
DeleteDir(true) ;
}
/// <summary>
/// 安装失败回滚时调用
/// </summary>
/// <param name="savedState"></param>
public override void Rollback(IDictionary savedState)
{
//保存状态
state = savedState ;
base.Rollback (savedState);
//删除虚拟目录
this.DeleteDir(false) ;
}
/// <summary>
/// 删除虚拟目录
/// </summary>
public void DeleteDir(bool flag)
{
//没有参数,直接用变量处理的,取中安装信息中安装的虚拟目录的状态,如果包含,则删除,否则不处理
if(state != null && state["InstDirVirtual"] != null )
{
string virname = (string)state["InstDirVirtual"] ;
//这段代码是删除虚拟目录的,网上有现成的代码,不再显示了
}
}
//添加一个虚拟目录
public void Createvir()
{
//得到虚拟目录和安装路径
string virname="";
string setupPath="";
string virPath="";
string apprPath="";
//下面取出的注册表的信息都是VS.NET安装程序中保存到注册表中的
RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\CorpName");
string keyName = key.GetValue("LastKey").ToString() ;
key.Close() ;
key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\CoprName\\" + keyName,true) ;
//取虚拟目录的名字,是VS.NET安装过程中增加的文本输入对话框保留的。
virname = key.GetValue("DirVirtual").ToString();
string virBak = virname ;
//安装目录也是同样的。
setupPath = key.GetValue("ProgramFolder").ToString();
virPath = Path.Combine( setupPath, keyName) + @"\";
//判断虚拟目录是否安装的代码,略
//把虚拟目录名保存到安装信息中,这些信息会保存到系统中以备卸载时使用
state["InstDirVirtual"] = virname ;
//其他处理
}
#region Component Designer generated code
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
using System.Xml;
using System.Collections;
using System.ComponentModel;
using System.Configuration.Install;
using Microsoft.Win32;
using System.IO;
namespace MyInstall
{
/// <summary>
/// CreateDirVirtual 的摘要说明。
/// </summary>
[RunInstaller(true)]
public class CreateDirVirtual : System.Configuration.Install.Installer
{
/// <summary>
/// 必需的设计器变量。
/// </summary>
private System.ComponentModel.Container components = null;
/// <summary>
/// 安装状态保存用的,也可以不定义做为参数传递给相应的方法
/// </summary>
private System.Collections.IDictionary state = null ;
public CreateDirVirtual()
{
// 该调用是设计器所必需的。
InitializeComponent();
// TODO: 在 InitComponent 调用后添加任何初始化
}
/// <summary>
/// 安装,即安装程序时会调用这个方法
/// </summary>
/// <param name="stateSaver"></param>
public override void Install(System.Collections.IDictionary stateSaver)
{
//保存安装信息
state = stateSaver ;
base.Install(stateSaver);
//创建虚拟目录的方法
this.Createvir();
}
/// <summary>
/// 卸载,当卸载程序时调用的方法
/// </summary>
/// <param name="savedState"></param>
public override void Uninstall(IDictionary savedState)
{
//保存状态。需要注意的是:安装和卸载时并不在一个进程中,所以savedState并不相同
state = savedState ;
base.Uninstall (savedState);
//删除虚拟目录
DeleteDir(true) ;
}
/// <summary>
/// 安装失败回滚时调用
/// </summary>
/// <param name="savedState"></param>
public override void Rollback(IDictionary savedState)
{
//保存状态
state = savedState ;
base.Rollback (savedState);
//删除虚拟目录
this.DeleteDir(false) ;
}
/// <summary>
/// 删除虚拟目录
/// </summary>
public void DeleteDir(bool flag)
{
//没有参数,直接用变量处理的,取中安装信息中安装的虚拟目录的状态,如果包含,则删除,否则不处理
if(state != null && state["InstDirVirtual"] != null )
{
string virname = (string)state["InstDirVirtual"] ;
//这段代码是删除虚拟目录的,网上有现成的代码,不再显示了
}
}
//添加一个虚拟目录
public void Createvir()
{
//得到虚拟目录和安装路径
string virname="";
string setupPath="";
string virPath="";
string apprPath="";
//下面取出的注册表的信息都是VS.NET安装程序中保存到注册表中的
RegistryKey key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\CorpName");
string keyName = key.GetValue("LastKey").ToString() ;
key.Close() ;
key = Registry.LocalMachine.OpenSubKey("SOFTWARE\\CoprName\\" + keyName,true) ;
//取虚拟目录的名字,是VS.NET安装过程中增加的文本输入对话框保留的。
virname = key.GetValue("DirVirtual").ToString();
string virBak = virname ;
//安装目录也是同样的。
setupPath = key.GetValue("ProgramFolder").ToString();
virPath = Path.Combine( setupPath, keyName) + @"\";
//判断虚拟目录是否安装的代码,略
//把虚拟目录名保存到安装信息中,这些信息会保存到系统中以备卸载时使用
state["InstDirVirtual"] = virname ;
//其他处理
}
#region Component Designer generated code
/// <summary>
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容。
/// </summary>
private void InitializeComponent()
{
components = new System.ComponentModel.Container();
}
#endregion
}
}
最后只要在安装部署的项目中增加上面的输出(程序集,我把安装类和安装部署项目放在一个解决方案中,直接增加项目输出即可),然后在安装部署项目的自定义操作中的安装、回滚、卸载操作中分别增加这个安装类项目的输入即可。
其实做起来非常简单,可能就是开始要自己写一些操作比较麻烦。如果不是特别需要,感觉这样更加灵活。更重要的是:免费的,不怕用破解的安装工具对企业不利了。