热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

.NETWeb应用程序安装包的制作经历:Sql数据库安装的3种方式

一次难得的安装包制作经历,因为之前从没有制作过安装包,那就免不了遇到问题,在摸索和学习中获得了不少宝贵经验,在这里我将用图文并茂的形式详细描述一下流程及主要难点问题的解决方法,希望

一次难得的安装包制作经历,因为之前从没有制作过安装包,那就免不了遇到问题,在摸索和学习中获得了不少宝贵经验,在这里我将用图文并茂的形式详细描述一下流程及主要难点问题的解决方法,希望对需要的朋友有所帮助.

      首先建一个Web应用程序的安装项目


bubuko.com,布布扣 >


      建好项目后在该安装项目的文件系统中加入Web应用程序的所有文件,全选后拖到"Web应用程序文件夹"内即可,也可以在"Web应用程序文件夹"点击右键在菜单中选择添加文件


bubuko.com,布布扣 >


      如果有多个Web应用程序需要放在同一个安装包内安装,可以在"目标计算机上的文件系统"上点右键添加"Web自定义文件夹",如图中的WebControls


bubuko.com,布布扣 >


      在Web文件夹的属性里,可以设置一下默认页及虚拟目录名称,其他的属性可以无视,使用默认值就可以了


bubuko.com,布布扣 >


      到此,一个Web应用程序的安装包就基本完成了,直接生成的安装程序就可以将安装到/Inetpub/wwwroot目录下成为一个虚拟站点了,如果你的站点没有数据库的话,基本可以打完收工了^_^

      之后遇到的第一个问题就是如何安装数据库.在网上找了一些资料,虽然说的比较详细,但都没有图例,习惯了傻瓜教程的我花了不少时间去摸索,下面就图文说明一下

      先设计用户录入SQL数据库信息的界面,这个VS.NET有现成的界面,稍微修改一下即可,非常简单,打开安装包项目的用户界面


bubuko.com,布布扣

      在"启动"项里添加一个"文本框(A)"对话框


bubuko.com,布布扣


      将"文本框(A)"移动到安装流程中合适的位置,设置一下属性,请注意,这里的EditProperty的值是传递用户输入数据的关键字,必填

 


bubuko.com,布布扣

 
      下面就进入重点了,这个流程的操作搞了半天才搞明白,在解决方案中再建一个类库项目,名字叫DBInstall,在该项目创建一个继承于System.Configuration.Install.Installer的类


bubuko.com,布布扣 >


      暂时不写代码,将此类库与安装项目关联起来先,在"Web应用程序文件夹"下的任意文件夹里点击右键添加一个"项目输出"


bubuko.com,布布扣


      默认会选中当前的DBInstall项目,不用改任何选项直接点确定,会在文件夹中新增一个"主输出来自DBInstall(活动)"的文件项


bubuko.com,布布扣


      接下来在项目自定义操作的"安装"项上点右键添加自定义操作,选择刚刚新增"主输出来自DBInstall(活动)"的文件夹,选中确定添加到安装项内


bubuko.com,布布扣 >


      添加完毕后设置"主输出来自DBInstall(活动)"的CustomActionData属性的值为
/dbname=[CUSTOMTEXTA1] /server=[CUSTOMTEXTA2] /user=[CUSTOMTEXTA3]
/pwd=[CUSTOMTEXTA4] /targetdir="[TARGETDIR]/"
,通过该格式化字符串接收用户输入传递给安装程序的自定义数据,前4个传入值是"文本框(A)"中相关联的TextBox的值,第5个参数"TARGETDIR"返回的是Web应用程序安装路径


bubuko.com,布布扣


      现在,可以去写安装Sql数据库的代码,在继承于System.Configuration.Install.Installer的InstallDb类中重载Install方法,在该方法内编写安装过程中需要执行的代码

      先编写个执行SQL语句的方法,后面编写安装数据库的代码时需要用到,传入的参数分别是
connStr - 数据库链接字符串,DatabaseName - 链接的数据库名称,Sql - 待执行的SQL语句


 1 private void ExecuteSql(string connStr, string DatabaseName, string Sql) {
 2             SqlConnection conn = new SqlConnection(connStr);
 3             SqlCommand cmd = new SqlCommand(Sql, conn);
 4 
 5             conn.Open();
 6             conn.ChangeDatabase(DatabaseName);
 7             try {
 8                 cmd.ExecuteNonQuery();
 9             }
10             finally {
11                 conn.Close();
12             }
13         }


      在研究过程中,我尝试了3种安装数据库的方法,下面将一一讲解一下

      第一种方法是通过附加数据库的方式来实现安装数据库,首先将需要安装的初始化数据库从Sql
Server中分离,将该数据库的mdf和ldf文件添加到"Web应用程序文件夹"中,这里是放在DataBase文件夹中的,在Install方法中添加以下代码



1 string connStr = string.Format("data source={0};user id={1};password={2};persist security info=false;packet size=4096", this.Context.Parameters["server"], this.Context.Parameters["user"], this.Context.Parameters["pwd"]);
2 string strSql = "EXEC sp_attach_db  @dbname  =  N‘" + this.Context.Parameters["dbname"] + "‘,"
3                                 + "@filename1  =  N‘" + this.Context.Parameters["targetdir"] + "DataBase//DemoData.mdf‘,"
4                                 + "@filename2  =  N‘" + this.Context.Parameters["targetdir"] + "DataBase//DemoData_log.ldf‘";
5 ExecuteSql(connStr, "master", strSql); 


      可以看到,通过this.Context.Parameters["KeyName"]的方法,可以获取由应用程序传递的自定义数据,获取数据库的相关信息拼成链接字符串,再拼一个附加数据库的SQL语句,用的是master库中的存储过程sp_attach_db,3个参数分别是数据库的名称,及mdf和ldf完整路径,因此要拼完整具体目录并加上文件名,这样,执行一下这个Sql语句即能将数据库附加到Sql
Server,但是这样做有个问题,卸载安装时安装程序会删除mdf和ldf文件,如果数据库在使用中,则卸载出错,如果数据库未使用,则被删除,后果严重,因此,只能用脚本去安装数据库

      第二种方法是从网上看来的,在进程中通过osql.exe去执行SQL脚本文件安装数据库



1 System.Diagnostics.Process sqlProcess = new System.Diagnostics.Process();
2 sqlProcess.StartInfo.FileName = "osql.exe";
3 sqlProcess.StartInfo.Arguments = string.Format(" -U {0} -P {1} -d {2} -i {3}/db.sql", this.Context.Parameters["user"], this.Context.Parameters["pwd"], this.Context.Parameters["dbname"], this.Context.Parameters["targetdir"]);
4 sqlProcess.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
5 sqlProcess.Start();
6 sqlProcess.WaitForExit(); //等待执行


      此种方法需要开一个进程,性能比较高,并且将进程的WindowStyle设置为Hidden,用户就看不到执行时的Dos窗体了,最后,一定要加上等待执行完成的WaitForExit方法,否则,数据库还未安装完成时安装程序很可能就已经完成安装提示用户可以退出了

      第三种方法是直接用先前所写的ExecuteSql方法执行安装脚本中的Sql语句



1 string connStr = string.Format("data source={0};user id={1};password={2};persist security info=false;packet size=4096", this.Context.Parameters["server"], this.Context.Parameters["user"], this.Context.Parameters["pwd"]);
2 ExecuteSql(connStr, "master", "CREATE DATABASE " + this.Context.Parameters["dbname"]);
3 
4 StringBuilder sb = this.GetSqlFile("Demo.sql");
5 ExecuteSql(connStr, this.Context.Parameters["dbname"], sb.ToString());
6 
7 sb = this.GetSqlFile("Demo_Data.sql");
8 ExecuteSql(connStr, this.Context.Parameters["dbname"], sb.ToString());


      通过GetSqlFile方法获得脚本中的Sql,这里用了两个脚本文件,一个是创建数据库的,一个是创建默认数据的,两个脚本文件是可以合并成一个文件的,执行一次即可



1 // 获取Sql文件里的脚本
2 private StringBuilder GetSqlFile(string pFileName) {
3             StringBuilder sqlTemp = new StringBuilder();
4 
5             sqlTemp.Append(File.ReadAllText(this.Context.Parameters["targetdir"] + "DataBase//" + pFileName, System.Text.Encoding.GetEncoding("GB2312")));
6 
7             return sqlTemp;
8 }


      需要提醒的是,创建数据库的脚本文件中,需要将"GO","SET
ANSI_NULLS ON","SET QUOTED_IDENTIFIER
ON"去掉,否则通过SqlCommand执行会出错,另外,如果默认数据的Insert脚本中包含中文,读取Sql语句时要加上System.Text.Encoding.GetEncoding("GB2312")这个参数,否则中文变乱码,默认数据的Insert脚本可以在网上找到导出所有数据Insert语句的存储过程

      3种安装数据库的方法中后两种比较实用,第一种方法虽然方便快捷,但是卸载时万一将数据库也误卸载,那就损失惨重了

      接下来说两个小问题,安装好了肯定要配置Web.Config中的数据库链接字符串,网上有现成的修改App.Config和Web.Config的方法,和安装数据库时的方法一样,拼好数据库链接字符串,调用修改Web.Config的方法,通过键名找到相应的键,将键值改为新的数据库链接字符串即可

      另一个问题是在不同系统环境下测试安装包时发现的,如果系统中有.NET
1.1和.NET 2.0两个环境,安装的虚拟站点默认使用1.1的.NET版本,如果系统先安装了.NET
2.0再安装IIS,那默认网站的ASP.NET版本选项是空的,没有选中2.0版本,因此安装的虚拟目录ASP.NET版本选项也是空的,问了不少网友,都说需要执行aspnet_regiis.exe
-i去注册2.0版本的.NET,但是如果安装好了再让用户去做这些操作总觉得有些别扭,看了一下aspnet_regiis.exe的参数说明,发现可以对某个虚拟站点进行.NET版本注册,就写下面这段代码去注册当天安装的虚拟目录



1 string path = Environment.GetFolderPath(Environment.SpecialFolder.System).ToUpper().Replace("SYSTEM32", "") + @"Microsoft.NET/Framework/v2.0.50727/aspnet_regiis.exe";
2 
3 System.Diagnostics.Process process = new System.Diagnostics.Process();
4 process.StartInfo.FileName = path;
5 process.StartInfo.Arguments = "-s
W3SVC/1/ROOT/" +
"虚拟站点名称";
6 process.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
7 process.Start();
8 process.WaitForExit();


      第一行的代码是获取aspnet_regiis.exe的具体路径,然后通过一个进程去执行注册操作,这样,即使出现前两种情况,都不用担心没有将虚拟站点的ASP.NET版本注册正确Web应用程序无法运行了

      这两部分代码可以建一个像安装数据库一样继承于System.Configuration.Install.Installer的自定义操作来执行,不过,方便起见,直接放在InstallDB类中就可以了

      安装包的制作是件很复杂的事,通过这次经历,只是学到了一点皮毛,在这里班门弄斧一下,希望对需要的朋友有所帮助^_^ 

.NET Web应用程序安装包的制作经历:Sql数据库安装的3种方式,布布扣,bubuko.com


推荐阅读
  • 本文介绍了OC学习笔记中的@property和@synthesize,包括属性的定义和合成的使用方法。通过示例代码详细讲解了@property和@synthesize的作用和用法。 ... [详细]
  • 知识图谱——机器大脑中的知识库
    本文介绍了知识图谱在机器大脑中的应用,以及搜索引擎在知识图谱方面的发展。以谷歌知识图谱为例,说明了知识图谱的智能化特点。通过搜索引擎用户可以获取更加智能化的答案,如搜索关键词"Marie Curie",会得到居里夫人的详细信息以及与之相关的历史人物。知识图谱的出现引起了搜索引擎行业的变革,不仅美国的微软必应,中国的百度、搜狗等搜索引擎公司也纷纷推出了自己的知识图谱。 ... [详细]
  • 本文介绍了lua语言中闭包的特性及其在模式匹配、日期处理、编译和模块化等方面的应用。lua中的闭包是严格遵循词法定界的第一类值,函数可以作为变量自由传递,也可以作为参数传递给其他函数。这些特性使得lua语言具有极大的灵活性,为程序开发带来了便利。 ... [详细]
  • GetWindowLong函数
    今天在看一个代码里头写了GetWindowLong(hwnd,0),我当时就有点费解,靠,上网搜索函数原型说明,死活找不到第 ... [详细]
  • 搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的详细步骤
    本文详细介绍了搭建Windows Server 2012 R2 IIS8.5+PHP(FastCGI)+MySQL环境的步骤,包括环境说明、相关软件下载的地址以及所需的插件下载地址。 ... [详细]
  • HDU 2372 El Dorado(DP)的最长上升子序列长度求解方法
    本文介绍了解决HDU 2372 El Dorado问题的一种动态规划方法,通过循环k的方式求解最长上升子序列的长度。具体实现过程包括初始化dp数组、读取数列、计算最长上升子序列长度等步骤。 ... [详细]
  • 本文介绍了C#中数据集DataSet对象的使用及相关方法详解,包括DataSet对象的概述、与数据关系对象的互联、Rows集合和Columns集合的组成,以及DataSet对象常用的方法之一——Merge方法的使用。通过本文的阅读,读者可以了解到DataSet对象在C#中的重要性和使用方法。 ... [详细]
  • 在说Hibernate映射前,我们先来了解下对象关系映射ORM。ORM的实现思想就是将关系数据库中表的数据映射成对象,以对象的形式展现。这样开发人员就可以把对数据库的操作转化为对 ... [详细]
  • 本文介绍了在SpringBoot中集成thymeleaf前端模版的配置步骤,包括在application.properties配置文件中添加thymeleaf的配置信息,引入thymeleaf的jar包,以及创建PageController并添加index方法。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • CSS3选择器的使用方法详解,提高Web开发效率和精准度
    本文详细介绍了CSS3新增的选择器方法,包括属性选择器的使用。通过CSS3选择器,可以提高Web开发的效率和精准度,使得查找元素更加方便和快捷。同时,本文还对属性选择器的各种用法进行了详细解释,并给出了相应的代码示例。通过学习本文,读者可以更好地掌握CSS3选择器的使用方法,提升自己的Web开发能力。 ... [详细]
  • 本文讨论了如何优化解决hdu 1003 java题目的动态规划方法,通过分析加法规则和最大和的性质,提出了一种优化的思路。具体方法是,当从1加到n为负时,即sum(1,n)sum(n,s),可以继续加法计算。同时,还考虑了两种特殊情况:都是负数的情况和有0的情况。最后,通过使用Scanner类来获取输入数据。 ... [详细]
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 本文讲述了作者通过点火测试男友的性格和承受能力,以考验婚姻问题。作者故意不安慰男友并再次点火,观察他的反应。这个行为是善意的玩人,旨在了解男友的性格和避免婚姻问题。 ... [详细]
author-avatar
LD系瑰精棂_142
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有