为了偷点“懒”,避免每次给用户安装系统时都要交给用户怎么样安装SQL Server,减少各种“麻烦”,终于狠心研究并整理了一下SQL Server自动安装的过程。本次使用的是SQL Server 2005Express,可从MSND中进行下载。
SQL Server 2005提供了很强大的功能,强大到至今都没有用到过。用的最多也是最基本的就是数据的存取,查询等。所以在给用户安装一个小型桌面程序时,也必要给客户安装一个文件大小2、3G的SQL Server吗,至少我认为这是一个很傻的选择,而且在这之前我一直这么很傻的干着。
转入正体,下面就说说SQL Server Express。
“Microsoft SQL Server 2005 Express Edition 是一种免费、易用的轻量版 SQL Server 2005,具有快速且易于掌握的特点,可用于快速开发和部署动态数据驱动的应用程序。” ----MSDN
前提是功能,因为我只用到了数据库的基本功能,数据存取、更新,包括存储过程,事务等,Express版本已经完全满足,并且使用和开发也其他版本没有任务区别,更重要的是“免费”,哈哈哈~~
OK,SQL Server2005 Express也分为32位和64位版本,考虑到客户机的不现系统,建议统一下载64位的版,因为可以同时在32的系统中进行安装,而32的位版本就不能在64位的系统中安装,这我可是试过的。下载地址:
还有一个需要注意的问题就是安装SQL Server 2005Express版本之前,系统需要安装.net Framework2.0,对于Vista和Win7的系统来说就不必了,可直接安装;2003系统和XP可能需要单独安装。因我的程序使用的都是.net进行开发的,所以必须首先进行.Net framework的安装,在这就没有考虑怎么自动安装。
自动安装思路:
1 使用命令行解压SQLExpr安装包(我把下载后的安装文件重命为SQLexpr),解压命令为 SQLexpr.exe /x <dir> /q
下图是解压后的目录结构:
2 创建自动安装脚本。其实就是一个批处理命令,并保存为一个.bat文件。
3 启动运行.bat文件。
4 附件需要安装的数据库,完成安装。
下面是实现代码:
1 解压数据库安装文件。启动一个进程Process,AppPath是当前程序的路径。
{
try
{
//ZipPath: 解压的目录
if (System.IO.Directory.Exists(ZipPath))
System.IO.Directory.Delete(ZipPath);
}
catch { }
finally
{
System.IO.Directory.CreateDirectory(ZipPath);
}
ShowMsg("开始解压...");
Process sqlProcess = new Process();
sqlProcess.StartInfo.FileName = AppPath + "sqlexpr.exe";
sqlProcess.StartInfo.Arguments = String.Format(" /x:\"{0}\" /q", ZipPath);
sqlProcess.StartInfo.WindowStyle = ProcessWindowStyle.Normal;
sqlProcess.Start();
sqlProcess.WaitForExit();
ShowMsg("解压完成...");
}
2 解压完成之后,就是如何创建安装命令了。其实完整的安装命令在解压完成后的目 录中已经有了完成说明,详细请参考目录中的"template.ini"文件。
2 {
3 StringBuilder sqlScript = new StringBuilder();
4 sqlScript.AppendLine("CLS ");
5 sqlScript.AppendLine("@ECHO OFF ");
6 sqlScript.AppendLine("ECHO. ");
7 sqlScript.AppendLine("ECHO ---------------------------------------------------------------- ");
8 sqlScript.AppendLine("ECHO To start the installation SQL SERVER 2005 ");
9 sqlScript.AppendLine("ECHO Please wait... ");
10 sqlScript.AppendLine("ECHO ---------------------------------------------------------------- ");
11 sqlScript.AppendLine("Start /wait setup.exe /qb INSTANCENAME=[实例名称] ADDLOCAL=All SECURITYMODE=SQL SAPWD=123456 SQLAUTOSTART=1 DISABLENETWORKPROTOCOLS=2 ");
12 sqlScript.AppendLine("ECHO ---------------------------------------------------------------- ");
13 sqlScript.AppendLine("ECHO Installation is complete... ");
14 sqlScript.AppendLine("ECHO ---------------------------------------------------------------- ");
15
16 using (System.IO.StreamWriter file = new System.IO.StreamWriter(ZipPath + "setup.bat", false, Encoding.ASCII))
17 {
18 file.Write(sqlScript.ToString());
19 }
20 }
这个方法就是创建了一个.bat批处理文件,到时我们执行这个批处理文件就可以了。其中最重要的就就是下面这行命令:
Start /wait setup.exe /qb INSTANCENAME=[实例名称] ADDLOCAL=All SECURITYMODE=SQL SAPWD=123456 SQLAUTOSTART=1 DISABLENETWORKPROTOCOLS=2
参数说明:
/qb 是 quiet mode,显示基本的图形界面,但是不用用户驱动,如果不想看到图形界面,可以用 /qn 参数。
INSTANCENAME 是实例名
ADDLOCAL 是安装所有的组件,可以指定安装哪些组件,请参考 template.ini 文件中详细说明
SECURITYMODE 服务器身份认证方式,分为windows身份验证模式,sql server和windows身份认证模式,此处指定为sql,则为第二种认证方式
SAPWD sa用户密码
SQLAUTOSTART 指定,安装完成后,sql server服务默认是自动开启的
DISABLENETWORKPROTOCOLS 指定网络协议参数,我这地方需要启动tcp/ip协议,所以设置为2,详细请参照 template.ini 中。
3 运行命令:
ShowMsg("开始安装数据库 ...");
Process sqlProcess = new Process();
sqlProcess.StartInfo.WorkingDirectory = ZipPath;
sqlProcess.StartInfo.FileName = ZipPath + "steup.bat";
sqlProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
sqlProcess.Start();
sqlProcess.WaitForExit();
ShowMsg("数据库安装完成...");
/完成之后,节省用户磁盘空间,删除解压的安装文件
Directory.Delete(ZipPath);
4 创建数据库附加脚本,并使用sqlcmd命令附加数据库.
下面的方法使用到了 xp_instance_regread 存储过程,用于查询连接的数据库实例的安装目录。因为在实际测试中发现附加数据库文件只能在..\MSQL\Data\目录下进行,其他目录会提示权限不足,另外以于Express数据库的备份文件也只能备份到..\MSQL\Backup\目录下,原因相同。所以,你的程序可能需要记录下这个目录,以便对数据库进行数据库备份或恢复操作是用到。
数据库使用了sp_attach_db 存储过程进行附加操作,并把 sp_attach_db的SQL脚本保存到了一个dbsql2005.sql临时文件中。
最后使用到 SqlCmd 命令执行sp_attach_db,参数如下:
String.Format(" -S {0} -i \"{1}\"", System.Net.Dns.GetHostName() + @"\[实例名]", paths);
sqlcmd.exe -s DELL-user1\SQLExpress -i c:\db2005.sql
{
/*
* 创建数据库
* 1.连接数据库(以Windows验证)
* 2.获取数据库安装目录(..\MSQL\Data\)
* 3.创建安装脚本,并通过SqlCmd命令执行脚本。
*/
String SmoRootPath = String.Empty;
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
SqlCommand cmd = new SqlCommand(
@" exec master.dbo.xp_instance_regread N'HKEY_LOCAL_MACHINE', N'SOFTWARE\Microsoft\MSSQLServer\Setup', N'SQLPath', @SmoRoot OUTPUT"
, conn);
cmd.CommandType = CommandType.Text;
SqlParameter rootPath = new SqlParameter("SmoRoot", SqlDbType.VarChar, 512);
rootPath.Direction = ParameterDirection.Output;
cmd.Parameters.Add(rootPath);
cmd.ExecuteNonQuery();
SmoRootPath = cmd.Parameters[0].Value.ToString();
conn.Close();
}
if (!string.IsNullOrEmpty(SmoRootPath))
{
//记录位置 HealthOneInBody SmoRootPath
ShowMsg("开始创建数据库文件...");
SmoRootPath = SmoRootPath + "\\Data\\";
String paths = AppPath + "db2005tp.sql";
CreateSql(paths, SmoRootPath);
Process sqlProcess = new Process();
sqlProcess.StartInfo.FileName = "sqlcmd.exe";
sqlProcess.StartInfo.Arguments = String.Format(" -S {0} -i \"{1}\"", System.Net.Dns.GetHostName() + @"\[实例名]", paths);
sqlProcess.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
sqlProcess.Start();
sqlProcess.WaitForExit();//'等待执行
ShowMsg("数据库文件创建完成...");
try
{
File.Delete(paths);
}
catch { }
}
}
/// <summary>
/// 数据库名:Dataname 文件名:Dataname.mdf Dataname.ldf ///
/// </summary>
/// <param name="paths">sql脚本文件路径</param>
/// <param name="dataPath">数据库文件路径</param>
private void CreateSql(String paths, String dataPath)
{
StringBuilder s = new StringBuilder();
s.AppendLine(String.Format("exec sp_attach_db @dbname=N'Dataname', @filename1=N'{0}Dataname.MDF',@filename2=N'{0}Dataname.LDF'", dataPath));
using (System.IO.StreamWriter configFile = new System.IO.StreamWriter(paths))
{
configFile.Write(s.ToString());
}
}