asp.net 部署数据库、开始菜单、桌面快捷方式实例

简单的ASP.NET部署,运行环境:vs2003,SqlServer2000

(一)前提:
http://www.microsoft.com/downloads/details.aspx?displaylang=zh-cn&FamilyID=627921a0-d9e7-43d6-a293-72f9c370bd19
下载"Microsoft Visual Studio .NET 2003 引导程序插件",它用于在 Microsoft® Visual Studio® .NET 2003 中创建包含 .NET Framework 1.1 版和/或 Microsoft Data Access Components (MDAC) 2.7 版的部署项目。

(二)建立简单的asp.net项目WebSetupTest

1.web.config文件里添加保存数据库连接字符串的key,部署的时候将初始化它.

< appSettings >
  
< add  key ="Conn_WebSetupTest"  value ="" ></ add >
</ appSettings >

2.
创建index.aspx文件

< form  id ="Form1"  method ="post"  runat ="server" >
   测试部署数据库和开始菜单/桌面快捷方式
   
< br >
   
< asp:DataGrid  id ="DataGrid1"  runat ="server"  Width ="100%"  AllowPaging ="True"  PageSize ="5" >
    
< PagerStyle  Mode ="NumericPages" ></ PagerStyle >
   
</ asp:DataGrid >< br >
   
< align ="center" >< img  src ="images/images_res.gif" ></ p >
</ form >

index.aspx.cs里绑定数据   

private   void  InitData()
        
{
            connE.strSql 
= "select * from users order by id desc";
            DataGrid1.DataSource 
= connE.GetDt();
            DataGrid1.DataBind();
        }

3.项目根目录下创建SqlScript目录用来存放部署数据需要的3个数据库脚本文件
 (1)CreateDataBase.sql用来创建数据库 --创建数据库<<DATABASE_NAME>>

Use  Master
Go
IF   EXISTS  ( SELECT  name  FROM  master.dbo.sysdatabases  WHERE  name  =   ' <<DATABASE_NAME>> ' )
 
DROP   DATABASE   [ <<DATABASE_NAME>> ]
GO
 
Create   Database   << DATABASE_NAME >>
Go

use   << DATABASE_NAME >>
-- 创建表
if   exists  ( select   *   from  dbo.sysobjects  where  id  =   object_id (N ' [dbo].[Users] ' and   OBJECTPROPERTY (id, N ' IsUserTable ' =   1 )
drop   table   [ dbo ] . [ Users ]
GO

CREATE   TABLE   [ dbo ] . [ Users ]  (
 
[ id ]   [ int ]   IDENTITY  ( 1 1 NOT   NULL  ,
 
[ name ]   [ varchar ]  ( 50 ) COLLATE Chinese_PRC_CI_AS  NULL  ,
 
[ address ]   [ varchar ]  ( 50 ) COLLATE Chinese_PRC_CI_AS  NULL  ,
 
[ createDate ]   [ datetime ]   NULL  
ON   [ PRIMARY ]
GO

 (2)InsertData.sql用来向数据库里插入记录

-- 增加记录
declare   @i   int
set   @i =   0

set  xact_abort  on
begin   transaction

while   @i < 50
begin
 
insert   into  users (name,address,createdate)  values  ( ' name ' + cast ( @i   as   varchar ), ' address ' + cast ( @i   as   varchar ), getDate ())
 
set   @i   =   @i + 1
end

-- rollback transaction
commit   transaction
set  xact_abort  off

(3)DropDataBase.sql用来卸载的时候删除数据库.

-- 删除数据库
IF   EXISTS  ( SELECT  name  FROM  master.dbo.sysdatabases  WHERE  name  =   ' <<DATABASE_NAME>> ' )
 
DROP   DATABASE   [ <<DATABASE_NAME>> ]

4.把快捷方式图标文件usa_folder_dialup.ico放在项目根目录下的确images目录里.

(三)在同一解决方案里添加"类库"项目WebSetupLib

1.把存放数据库脚本文件名称的DataBase.xml和用户许可协议文件UserProtocol.rtf放在Resources目录下.
UserProtocol.rtf文件可以通过Word直接创建,DataBase.xml要作为嵌入式资源,设置方法如图:


DataBase.xml内容:

<? xml version="1.0" encoding="utf-8"  ?>  
< configroot >
 
< Files >
  
< DataBase >
   
< Add >
    
< File  name ="CreateDataBase.sql" />
   
</ Add >
   
< Remove >
    
< File  name ="DropDataBase.sql" />
   
</ Remove >
  
</ DataBase >
  
< Insert >
   
< File  name ="InsertData.sql" />
  
</ Insert >
  
 
</ Files >  
</ configroot >

2.添加部署数据库的类文件DataBase.cs,在下面的安装程序类文件WebSetupTest.cs里将使用此类
sing System;
using System.Diagnostics;
using System.Configuration.Install;
using System.Xml ;
using System.Windows.Forms;

namespace WebSetupLib
{
 /** <summary>
 /// DataBase 的摘要说明。
 /// </summary>
 public class DataBase
 {
  string serverName=null;
  string databaseName =null;
  string userName=null;
  string Password=null;
  bool trustedconnection=false;
  string targetPath=null;
  XmlDocument config=null;
  public const string CONST_DATBASE_PLACEHOLDER ="<<DATABASE_NAME>>";
 
  //构造方法#region //构造方法
  public DataBase()
  {
   //
   // TODO: 在此处添加构造函数逻辑
   //
   //System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("WebSetupLib.DataBase.xml");
   System.IO.Stream stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("WebSetupLib.Resources.DataBase.xml");
   config=new XmlDocument();
   //MessageBox.Show("before load1111");
   config.Load(stream);
   //MessageBox.Show("after load 111");
  }

  public DataBase(string servername,string databasename,string username,
   string password,string targetpath):this()
  {
   this.serverName =servername;
   this.databaseName=databasename;
   this.userName=username;
   this.Password=password;
   this.targetPath=targetpath;
  }
  /** <summary>
  /// 信任连接
  /// </summary>
  /// <param name="servername"></param>
  /// <param name="databasename"></param>
  /// <param name="targetpath"></param>
  public DataBase(string servername,string databasename,string targetpath):this()
  {
   this.serverName =servername;
   this.databaseName=databasename;
   this.trustedconnection=true;
   this.targetPath =targetpath;
  }

  #endregion

  /** <summary>
  /// 安装数据库
  /// </summary>
  /// <returns></returns>
  public  bool  CreateDataBase()
  {
   string fileName=null;
   try
   {
    ProcessStartInfo processInfo =new ProcessStartInfo("osql.exe");
    processInfo.WindowStyle=ProcessWindowStyle.Hidden;

    //Get the name of the file from the assembly's embedded resource.
    //MessageBox.Show("createDatabase");
    if(config !=null)
    {
     fileName = config.SelectSingleNode("configroot/Files/DataBase/Add/File").Attributes["name"].Value;
    }
    else
    {
     throw new InstallException("创建数据库的脚本文件不存在!");
    }

    //Get arguments
    //MessageBox.Show("master");
    processInfo.Arguments=GetCommonProcessArguments(fileName,"master");
    
    EventLog.WriteEntry("安装数据库",processInfo.Arguments);
    PopulateDatabaseNamePlaceHolder(GetFullPath(fileName));
    Process osql = Process.Start(processInfo);
    //Wait till it is done
    osql.WaitForExit();
    EventLog.WriteEntry( "安装数据库","数据库创建完成..");
    osql.Dispose();
    return true;
   }
   catch(Exception ex)
   {
    //Customize if required.
    EventLog.WriteEntry("安装数据库",ex.Message,EventLogEntryType.Error) ;
    throw new InstallException(ex.Message);
   }
  }
 
  /** <summary>
  /// 删除数据库
  /// </summary>
  /// <returns></returns>
  public bool DropDataBase()
  {
   string fileName=null;
   try
   {
    ProcessStartInfo processInfo =new ProcessStartInfo("osql.exe");
    processInfo.WindowStyle=ProcessWindowStyle.Hidden;
   
    //Get the name of the file from the assembly's embedded resource.
    if(config !=null)
    {
     fileName = config.SelectSingleNode("configroot/Files/DataBase/Remove/File").Attributes["name"].Value;
    }
    else
    {
     throw new InstallException("删除数据库的脚本文件不存在!");
    }
     
    //Get arguments
    processInfo.Arguments=GetCommonProcessArguments(fileName,"master");

    EventLog.WriteEntry("安装数据库",processInfo.Arguments);
    PopulateDatabaseNamePlaceHolder(GetFullPath(fileName));
    Process osql = Process.Start(processInfo);
    osql.WaitForExit();
    EventLog.WriteEntry("安装数据库","删除数据库");
    osql.Dispose();
    return true;
   }
   catch(Exception ex)
   {
    //Customize if required.
    EventLog.WriteEntry("安装数据库",ex.Message,EventLogEntryType.Error) ;
    throw new InstallException(ex.Message);
   }
  }
 
  /** <summary>
  /// 插入数据
  /// </summary>
  /// <returns></returns>
  public bool InsertDate()
  {
   try
   {
    ExecuteScripts("configroot/Files/Insert/File");
    EventLog.WriteEntry("安装数据库","记录增加完成");
    return true;
   }
   catch(Exception ex)
   {
    //Customize if required.
    EventLog.WriteEntry("安装数据库",ex.Message,EventLogEntryType.Error) ;
    throw new InstallException(ex.Message);
   }
  }
 
  /** <summary>
  /// 执行数据库脚本
  /// </summary>
  /// <param name="Xpath"></param>
  void ExecuteScripts(string Xpath)
  {
   XmlNodeList objectlist=null;
   ProcessStartInfo processInfo =new ProcessStartInfo("osql.exe");
   processInfo.WindowStyle=ProcessWindowStyle.Hidden;

   //Get the name of the file from the assembly's embedded resource.
   if(config !=null)
   {
    objectlist = config.SelectNodes(Xpath);
   }
   else
   {
    throw new InstallException("保存数据库脚本文件名称的XML文件不存在!");
   }

   foreach(XmlNode objectFile in objectlist)
   {
    //Get arguments
    processInfo.Arguments=GetCommonProcessArguments(objectFile.Attributes["name"].Value,databaseName);
    EventLog.WriteEntry("安装数据库",processInfo.Arguments);
    Process osql = Process.Start(processInfo);
    //Wait till it is done
    osql.WaitForExit();
    EventLog.WriteEntry( "安装数据库", objectFile.InnerText +" file executed..");
   }
  }

  /** <summary>
  /// 获得数据库脚本的完整路径
  /// </summary>
  /// <param name="fileName"></param>
  /// <returns></returns>
  private string GetFullPath(string fileName)
  {
   //The destination folder for this will be the Install/scripts folder under the
   //installation root
   //MessageBox.Show(targetPath + @"SqlScript/" + fileName);
   string FullPath = targetPath + @"SqlScript/" + fileName;
   return FullPath;
  }
 
  /** <summary>
  /// 读数据库脚本文件的内容
  /// </summary>
  /// <param name="filepath"></param>
  void PopulateDatabaseNamePlaceHolder(string filepath)
  {
   //Read the contents
   System.IO.StreamReader reader = new System.IO.StreamReader(filepath);  
   string content=reader.ReadToEnd();
   reader.Close();
   //Replace the placeholder with database name
   content =content.Replace(CONST_DATBASE_PLACEHOLDER,databaseName);
   //Writeback the contents
   System.IO.StreamWriter writer = new System.IO.StreamWriter(filepath,false);
   //MessageBox.Show(content);
   writer.Write(content);
   writer.Flush();
   writer.Close();
  }

  string GetCommonProcessArguments(string fileName, string overridendatabasename)
  {
   //是否是信任连接
   if(!trustedconnection)
   {
    /**//* Arguments configured.
      *  osql [-S server] [-d use database name]   [-U login id] [-P password]
      [-i inputfile]  [-o outputfile]
     */
    return " -S " + serverName + " -d " + overridendatabasename +" -U " + userName + " -P " +Password + " -i " + Char.ToString('"') +  GetFullPath(fileName) + Char.ToString('"') + " -o " + Char.ToString('"') + targetPath +  "Log.txt" + Char.ToString('"'); 
   }
   else
   {
    /**//* Arguments configured.
      *  osql [-S server] [-d use database name]   [-E trusted connection]
      [-i inputfile]  [-o outputfile]
     */
    return " -S " + serverName + " -d " + overridendatabasename + " -E " + " -i " + Char.ToString('"') +  GetFullPath(fileName) + Char.ToString('"') + " -o " + Char.ToString('"') + targetPath + "Log.txt" + Char.ToString('"'); 
   }
  }
 }


 3.添加安装程序类文件WebSetupTest.cs 里面重载Install和Uninstall方法.
public override void Install(IDictionary stateSaver)
  {
   bool TrustedConnection=false;
   base.Install (stateSaver);
   try
   {
    if(this.Context!=null)
    {
     StringDictionary parameters = Context.Parameters  ;
     string[] keys =new string[parameters.Count];
     parameters.Keys.CopyTo(keys,0);

 

     "把数据库/服务器名/数据库用户名/数据库密码/安装路径写进 stateSaver"#region "把数据库/服务器名/数据库用户名/数据库密码/安装路径写进 stateSaver"
     //MessageBox.Show(this.Context.Parameters["target"].ToString());
     stateSaver.Add("database",this.Context.Parameters["database"].ToString()); 
     stateSaver.Add("server",this.Context.Parameters["server"].ToString()); 
     stateSaver.Add("username",this.Context.Parameters["username"].ToString()); 
     stateSaver.Add("password",this.Context.Parameters["password"].ToString()); 
     stateSaver.Add("target",this.Context.Parameters["target"].ToString());
     #endregion

     //测试连接#region //测试连接
     //can encrypt here
     string connectionstring= "Data Source=" + stateSaver["server"].ToString() ;
     connectionstring+= ";Initial Catalog=" + stateSaver["database"].ToString() ;
     if(stateSaver["username"]!=null && stateSaver["username"].ToString().Length!=0)
     {
      SqlConnection conn =new SqlConnection( "server=" + stateSaver["server"].ToString()
       + ";database=master;Uid=" + stateSaver["username"].ToString() +";Password=" + stateSaver["password"].ToString());
      conn.Open();
      conn.Close();
      conn.Dispose();
      connectionstring+= ";User ID=" + stateSaver["username"].ToString() ;
      connectionstring+= ";Password=" + stateSaver["password"].ToString() ;
     }
     else
     {
      //信任连接
      SqlConnection conn =new SqlConnection( "Data Source=" + stateSaver["server"].ToString()
       + ";Initial Catalog=master;trusted_connection=yes");
      conn.Open();
      conn.Close();
      conn.Dispose();
      TrustedConnection=true;
      stateSaver.Add("trustedconnection",true);
      connectionstring+=";Trusted_connection=yes";
     }
     #endregion

     //把数据库连接字符串写进web.config文件.#region //把数据库连接字符串写进web.config文件.
     XmlDocument doc = new XmlDocument();
     doc.Load(stateSaver["target"].ToString()+ @"Web.config");
     XmlNode connectionNode = doc.SelectSingleNode(@"configuration/appSettings/add[@key='Conn_WebSetupTest']");
     if(connectionNode!=null)
     {
      connectionNode.Attributes["value"].Value = connectionstring;
      doc.Save( stateSaver["target"].ToString()+ @"Web.config");
      EventLog.WriteEntry("安装数据","Configuration file processed"); //写日志
     }
     else
     {
      //This error will ensure installation is uncomplete
      throw new InstallException("没有数据库连接串!");
     }
     #endregion
     //执行数据库脚本,安装数据库#region //执行数据库脚本,安装数据库
     DataBase dbInstall =null;
     if(TrustedConnection)
     { 
      dbInstall= new DataBase(stateSaver["server"].ToString(),stateSaver["database"].ToString(),
       stateSaver["target"].ToString());
     }
     else
     {
      dbInstall= new DataBase(stateSaver["server"].ToString(),stateSaver["database"].ToString(),
       stateSaver["username"].ToString(),stateSaver["password"].ToString(),stateSaver["target"].ToString());
     }
     dbInstall.CreateDataBase();
     dbInstall.InsertDate();
     #endregion

     //部署桌面快捷方式*******************#region//部署桌面快捷方式*******************
     StreamWriter sw2=System.IO.File.CreateText(Context.Parameters["des"].ToString()+"WebSetupTest.url");
     stateSaver.Add("DeskQuick",Context.Parameters["des"].ToString()+"WebSetupTest.url"); //保存桌面快诫方式文件绝对地址
     //Context.Parameters["des"].ToString()是对应的桌面地址
     string webdirs=Context.Parameters["webdir"].ToString();
     //Context.Parameters["webdir"].ToString()对应的路径,在安装项目里面作为参数传入
     string webdirsNew = webdirs.Substring(0,webdirs.Length-1);
     webdirs = webdirsNew.Substring(webdirsNew.LastIndexOf(@"/")+1);
     string Urls=@"URL=http://localhost/"+webdirs+@"/index.aspx";
     sw2.WriteLine("[InternetShortcut]");
     sw2.WriteLine(Urls);
     sw2.WriteLine("modified=228928983");
     sw2.WriteLine("IconIndex=0");
     //sw2.WriteLine("IconFile="+webdirsNew+"//Resources//usa_folder_dialup.ico");
     sw2.WriteLine("IconFile="+webdirsNew+"//images//usa_folder_dialup.ico");
     sw2.Flush();
     sw2.Close();
     #endregion

     部署开始菜单 ***************#region 部署开始菜单 ***************
     string startMenue=Environment.GetFolderPath(Environment.SpecialFolder.StartMenu);
     if(File.Exists(startMenue+"//WebSetupTest.url"))
     {
      if(MessageBox.Show("开始菜单已经存在,是否有覆盖它?","安装开始菜单",MessageBoxButtons.YesNo,MessageBoxIcon.Question,
       MessageBoxDefaultButton.Button1) == DialogResult.Yes)
      {
                    
       File.Copy(Context.Parameters["des"].ToString()+"WebSetupTest.url",startMenue+"//WebSetupTest.url",true);
      }
      else
      {
       throw new InstallException("开始菜单已经存在,安装取消");
      }
     }
     else
     {
      File.Copy(Context.Parameters["des"].ToString()+"WebSetupTest.url",startMenue+"//WebSetupTest.url",false);
     }
     stateSaver.Add("StartMenueFile",startMenue+"//WebSetupTest.url"); //保存开始菜单文件绝对地址
     #endregion
    }
   }
   catch(Exception ex1)
   {
    throw new System.Configuration.Install.InstallException(ex1.ToString());
   }
  }

  public override void Uninstall(IDictionary savedState)
  {
   try
   {
    if(savedState!=null)
    {
     base.Uninstall (savedState);

     删除快捷键,删除开始菜单#region 删除快捷键,删除开始菜单
     //删除快捷键
     if(File.Exists(savedState["DeskQuick"].ToString()))
     {
      File.Delete(savedState["DeskQuick"].ToString());
     }
     //删除开始菜单
     if(File.Exists(savedState["StartMenueFile"].ToString()))
     {
      File.Delete(savedState["StartMenueFile"].ToString());
     }
     #endregion

     //删除数据库#region //删除数据库
     if(MessageBox.Show("要删除数据库吗?" +savedState["database"].ToString()+"./n ","确认删除数据库",MessageBoxButtons.YesNo,MessageBoxIcon.Question  ,MessageBoxDefaultButton.Button2)== DialogResult.No)    
     {
      return;
     }
     DataBase dbInstall=null;
     if(savedState["trustedconnection"]!=null && (bool)savedState["trustedconnection"])
     {
      dbInstall= new DataBase(savedState["server"].ToString(),savedState["database"].ToString(),
       savedState["target"].ToString());
     }
     else
     {
      dbInstall= new DataBase(savedState["server"].ToString(),savedState["database"].ToString(),
       savedState["username"].ToString(),savedState["password"].ToString(),savedState["target"].ToString());
     }
     dbInstall.DropDataBase();
     #endregion
    }
    else
    {
     MessageBox.Show("Saved state was nullsome error.");
     throw new ApplicationException("卸载需要的参数不存在!");
    }
   }
   catch(InstallException inst)
   {
    throw new InstallException(inst.Message);
   }
   catch(Exception generic)
   {
    throw new InstallException(generic.Message);
   }
  }

(四)在同一解决方案里添加'Web安装项目"WebSetup

1.打开"文件系统"视图
(1)"web应用程序文件夹"-->右键"添加"-->"项目输出" 选择"WebSetupTest"里的"主输出"和"内容文件",如下图:

主输出一般是dll文件,内容文件包括aspx文件/web.config/images目录等等.

(2)"web应用程序文件夹"--新建目录"install",然后"install"右键"项目输出" 选择"WebSetupLib"里的"主输出"和"内容文件"

2.打开"用户界面"视图.
(1)."安装"--"启动"-->右键"添加对话完"--"许可协议".
添加完毕后在"许可协议"的"属性窗口"中添加刚才的UserProtocol.rtf文件.
(2).用上面一样的方法添加"文本框(A)",在其属性里设置服务器和数据库信息


下图是上面是两个对话框添加完毕后的"用户界面"视图.

3.打开"自定义操作"视图.

(1)"安装"-->右键"添加自定义操作"选择"install"目录下的"主输出来自WebSegtupLib",命名为Install
它是设置自定义的数据/快捷方式/开菜单等.


(2)在上面的install属性窗口里"CustomActionData"的值为/server=[SERVER_NAME] /target="[TARGETDIR]/" /database=[DATABASE_NAME] /username=[USER_NAME] /password=[PASSWORD] /version=[WINDOWSVERSION] /des="[DesktopFolder]/" /webdir="[TARGETDIR]/"

(3)"卸载"--右键"添加自定义操作"选择"install"目录下的"主输出来自WebSegtupLib".命名为UnInstall
这样卸载的时候将删除数据库/快捷方式/开菜单等.下图是两个子定义操作后的"自定义操作"视图.


4."启动条件"视图使用默认值.
五.编译安装项目

编译后将生成WebSetup.msi安装文件.这样就可以安装了.下面是安装效果图




六.参考资料

自定义 MSI 安装(里面有详细的数据库部署代码实例)
http://www.netscum.dk/china/msdn/library/langtool/vsdotnet/usvs04j7.mspx

 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值