C#打包--如何用VS2005制作Web安装程序

转自:http://blog.sina.com.cn/s/blog_7f13f92a0100rkch.html
网站完成后,需要部署到目标机器上,方法有很多,直接把文件Copy到目标机器上,执行SQL脚本,配置IIS,这样可以做到;也可以使用InstallShield这样到专业制作软件来打包。本篇文章是使用VS2005自带到安装部署工具来制作exe安装文件。

涉及到到内容包括:使用安装部署工具,建立数据库,配置IIS,文件操作,注册表等。参考了网上关于使用VS制作安装程序的文章。环境:Windows2003+ VS2005 + SQL2005。

注:本文只是为了实现,没有强调方法,变量等的写法标准。

使用VS2005制作安装程序的时候,有多种选择,如下图:

C#打包--如何用VS2005制作Web安装程序(上)

我想一般常用的可能就最上面的两种。当使用Web安装项目时,执行制作好的msi安装文件时,会发现实际上是添加虚拟目录而不是添加网站,而且无法选择安装目录,当然,可以自己写脚本来对IIS进行修改。不过在这篇文章里,将不采用此模式。本篇文章用的是使用“安装项目”,就和打包WinForm程序一样,把Web文件部署到目标机器上,然后重写install方法,配置IIS,执行SQL脚本,修改web.config文件等。

在开始整个过程之前,需要先了解一下“预编译”的概念,MSDN上的说明是:默认情况下,在用户首次请求资源(如网站的一个页)时,将动态编译ASP.NET网页和代码文件。第一次编译页和代码文件之后,会缓存编译后的资源,这样将大大提高随后对同一页提出的请求的效率。请查阅MSDN“预编译”相关文档。

准备一个文件DBSQL.txt,在里面包含连接数据库后需要执行的SQL脚本,在本例中使用了简单的一个CreateTabel的SQL。

好了,现在开干,吼吼~~~~~~~~~~

打开VS2005,打开一个网站项目,这里是打开的本地localhost,如图:

C#打包--如何用VS2005制作Web安装程序(上)

新加一个页面,随便取个名字(本文中为ClientCallback.aspx),然后写一个简单的按钮事件即可,这不是本文的重点,由你随意处理^_^再添加web配置文件即web.config,在下添加
          
此文件到时候是需要发布到目标机器上的。(关于连接数据库字符串,VS2005里面有专门的connectionStrings,本文未使用,可查阅帮助)

点击生成网站,访问页面,ok!

选择菜单生成=》发布网站:

C#打包--如何用VS2005制作Web安装程序(上)

点击确定后,网站已经生成,这些就是需要部署到目标机器上的所有文件。

点击菜单文件=》添加=》新建项目,添加安装部署项目,如图:

C#打包--如何用VS2005制作Web安装程序(上)

添加安装项目类库:

C#打包--如何用VS2005制作Web安装程序(上)

删除默认的Class1.cs,新加一个安装程序类文件,名为MyInstaller.cs:

C#打包--如何用VS2005制作Web安装程序(上)


在此项目中,添加对System.EnterpriseServices和System.DirectoryServices的引用,在操作IIS的时候,需要用到。在文件中添加:

usingSystem;

usingSystem.IO;

usingSystem.DirectoryServices;

usingSystem.Reflection;

usingSystem.Data;

usingSystem.Data.SqlClient;

usingSystem.Configuration.Install;

usingSystem.Management;

usingSystem.Collections;

usingMicrosoft.Win32;

usingSystem.Collections.Specialized;如果编译的时候出错,请添加相关引用。

修改文件如下图:

C#打包--如何用VS2005制作Web安装程序(上)


注意要手动添加Installer!

将DBSQL.txt文件放到此项目中,在属性中设置为“嵌入的资源”

C#打包--如何用VS2005制作Web安装程序(上)

回到MyWebSetup项目,点击查看属性,可以设置安装文件到显示相关信息,如图

C#打包--如何用VS2005制作Web安装程序(上)

选择文件系统,如图:

C#打包--如何用VS2005制作Web安装程序(上)

然后:

C#打包--如何用VS2005制作Web安装程序(上)

(在文件系统中,在属性里面可以设置安装程序默认到安装路径)

添加一个叫bin文件夹并添加在生成网站时bin目录下的dll文件,如图:

C#打包--如何用VS2005制作Web安装程序(上)

在应用程序文件夹下在生成网站时目录下的文件,添加后如图:

C#打包--如何用VS2005制作Web安装程序(上)


选择“用户界面编辑器”,添加两个文本框A和B,A将作为安装新站点后的IIS设置,B将作为数据库操作时的参数设置,调整位置后如下:

C#打包--如何用VS2005制作Web安装程序(上)

调整A的属性,这里只选择了显示两个输入框,属性分别为IISSERVER和PORT,值为localhost和9998,其他的你可以自己调整。如图:

C#打包--如何用VS2005制作Web安装程序(上)

文本框B的设置如下:

C#打包--如何用VS2005制作Web安装程序(上)

OK,文本框设置完毕。当然,你还可以选择其他的多种文本框,如协议什么的。

打开自定义操作面板:

C#打包--如何用VS2005制作Web安装程序(上)

C#打包--如何用VS2005制作Web安装程序(上)

然后:

C#打包--如何用VS2005制作Web安装程序(上)

在CustomActionData中输入:

/dbname=[DBNAME] /server=[DBSERVERNAME] /user=[USERNAME]/pwd=[PASSWORD] /iis=[IISSERVER] /port=[PORT]/targetdir="[TARGETDIR]"

这些参数就是文本框A和B上的输入框的值,在安装过程中可以获得,然后进行处理。

至此,基本的安装文件已经制作完毕。进行生成,然后点击安装,可以看到文件已经复制到了相应到目录。接下来就要接收参数对IIS和数据库进行处理。

打开SetupClassLibrary项目下的MyInstaller.Designer.cs,修改此文件。

申明几个变量:

       privateSystem.Data.SqlClient.SqlConnection sqlConn;

       privateSystem.Data.SqlClient.SqlCommand Command;

       private stringDBName;

       private stringServerName;

       private stringAdminName;

       private stringAdminPwd;

   

       private stringiis;

       private stringport;

       private stringdir;

       public static stringVirDirSchemaName = "IIsWebVirtualDir";

       private string_target;

       private DirectoryEntry_iisServer;

       private ManagementScope_scope;

       private ConnectionOptions_connection;

连接数据库服务器到方法:

#regionConnectDatabase 连接数据库

       private boolConnectDatabase()

       {

          if (Command.Connection.State !=ConnectionState.Open)

          {

             try

             {

                Command.Connection.Open();

             }

             catch(Exception e)

             {

                 return false;

             }

          }

          return true;

       }

       #endregion

如果不能正确连接数据库服务器,请检查你的连接字符串,或者将连接字符串写入文件查看。不好意思,我不知道如何对这种安装部署程序进行debug,sorry咯!

读取SQL文件的方法:

#region GetSql从文件中读取SQL,在读取包含SQL脚本的文件时需要用到,参考自MSDN

       private string GetSql(stringName)

       {

          try

          {

              AssemblyAsm = Assembly.GetExecutingAssembly();

              Stream strm= Asm.GetManifestResourceStream(Asm.GetName().Name + "." +Name);

             StreamReader reader = newStreamReader(strm);

              returnreader.ReadToEnd();

          }

          catch (Exception getException)

          {

              throw newApplicationException(getException.Message);

          }

       }

       #endregion

可以将此需要执行的SQL脚本放在此文本中

执行SQL语句的方法:

#regionExecuteSql 执行SQL语句,参考自MSDN

       private void ExecuteSql(stringDataBaseName, string sqlstring)

       {

          Command = newSystem.Data.SqlClient.SqlCommand(sqlstring, sqlConn);

          if (ConnectDatabase())

          {

             try

             {

                Command.Connection.ChangeDatabase(DataBaseName);

                Command.ExecuteNonQuery();

             }

             finally

             {

                Command.Connection.Close();

             }

          }

       }

       #endregion

创建数据库及数据库表:

#regionCreateDBAndTable 创建数据库及数据库表,参考自MSDN

       protected boolCreateDBAndTable(string DBName)

       {

         

          bool Restult = false;

          try

          {

             ExecuteSql("master", "USE MASTER IF EXISTS(SELECT NAME FROM SYSDATABASES WHERE NAME='" + DBName + "') DROPDATABASE " + DBName);

             ExecuteSql("master", "CREATE DATABASE " +DBName);

             ExecuteSql(DBName,GetSql("DBSQL.txt"));

            

              Restult =true;

          }

          Catch

         

          {

          }

          return Restult;

       }

       #endregion

从备份文件恢复数据库及数据库表

#regionRestoreDB 从备份文件恢复数据库及数据库表

       ///

       ///从备份文件恢复数据库及数据库表

       ///

       /// 数据库名

       /// 配件中数据库脚本资源的名称

       ///

       protected boolRestoreDB(string DBName)

       {

          dir =this.Context.Parameters["targetdir"];

          bool Restult = false;

          string MSQL = "RESTORE DATABASE " + DBName+

              " FROM DISK= '" + dir + @"data.bak' " +

              " WITH MOVE'Test' TO '" + @"c:" + DBName + ".mdf', " +

              " MOVE'Test_log' TO '" + @"c:" + DBName + ".ldf' ";

          try

          {

             ExecuteSql("master", "USE MASTER IF EXISTS(SELECT NAME FROM SYSDATABASES WHERE NAME='" + DBName + "') DROPDATABASE " + DBName);

             ExecuteSql("master", MSQL);

              Restult =true;

          }

          finally

          {

              //删除备份文件

             try

             {

                 File.Delete(dir +@"data.bak");

             }

             catch

             {

             }

          }

          return Restult;

       }

       #endregion

这里可以到注册表读取SQLServer的安装路径,把恢复后的数据库文件放到data目录地下。在本例中,只是实现了恢复,并未进行标准的操作。其中Test和Test_log时备份时数据库的文件信息。如果想要从备份文件中恢复,请把文件包含到项目里并且设置和DBSQL.txt一样,嵌入到程序里。最后执行删除。不过我想应该有办法不把文件先安装到目标机器上,而是有方法想读取DBSQL.txt文件一样,直接恢复数据库,不过确实没想到办法,失败!

网站安装好后,需要设置web.config文件,这里只涉及到连接字符串到设置,其他的可以同理修改。

       #region WriteWebConfig修改web.config的连接数据库的字符串

       private boolWriteWebConfig()

       {

          System.IO.FileInfo FileInfo = newSystem.IO.FileInfo(this.Context.Parameters["targetdir"] +"/web.config");

          if (!FileInfo.Exists)

          {

              throw newInstallException("Missing config file :" +this.Context.Parameters["targetdir"] + "/web.config");

          }

          System.Xml.XmlDocument xmlDocument = newSystem.Xml.XmlDocument();

          xmlDocument.Load(FileInfo.FullName);

          bool FoundIt = false;

          foreach (System.Xml.XmlNode Node inxmlDocument["configuration"]["appSettings"])

          {

              if(Node.Name == "add")

             {

                 if(Node.Attributes.GetNamedItem("key").Value =="ConnectionString")

                 {

                    Node.Attributes.GetNamedItem("value").Value =String.Format("Persist Security Info=False;DataSource={0};database={1};User ID={2};Password={3};PacketSize=4096;Pooling=true;Max Pool Size=100;Min Pool Size=1",ServerName, DBName, AdminName, AdminPwd);

                    FoundIt = true;

                 }

             }

          }

          if (!FoundIt)

          {

              throw newInstallException("Error when writing the config file:web.config");

          }

          xmlDocument.Save(FileInfo.FullName);

          return FoundIt;

       }

       #endregion

#region WriteRegistryKey写注册表。安装部署中,直接有一个注册表编辑器,可以在那里面设置。

       privatevoid WriteRegistryKey()

      {

          // 写注册表

          RegistryKey hklm =Registry.LocalMachine;

          RegistryKey cqfeng =hklm.OpenSubKey("SOFTWARE", true);

          RegistryKey F =cqfeng.CreateSubKey("cqfeng");

          F.SetValue("FilePath","kkkk");

      }

      #endregion

操作IIS,建立网站等。可参考:

用VS2005制作网页对IIS进行操作

#region Connect 连接IIS服务器

       public boolConnect()

      {

          if (iis == null)

             return false;

          try

          {

             _iisServer = new DirectoryEntry("IIS://" + iis +"/W3SVC/1");

             _target = iis;

             _connection = newConnectionOptions();

             _scope = new ManagementScope(@"\" + iis +@"\root\MicrosoftIISV2", _connection);

             _scope.Connect();

          }

          catch

          {

               return false;

          }

          returnIsConnected();

      }

       public boolIsConnected()

      {

          if (_target == null ||_connection == null || _scope == null) return false;

          return_scope.IsConnected;

      }

      #endregion

#region IsWebSiteExists判断网站是否已经存在

       public boolIsWebSiteExists(string serverID)

      {

          try

          {

             string siteName = "W3SVC/" +serverID;

             ManagementObjectSearcher searcher = newManagementObjectSearcher(_scope, new ObjectQuery("SELECT * FROMIIsWebServer"), null);

             ManagementObjectCollection webSites =searcher.Get();

             foreach (ManagementObject webSite inwebSites)

             {

                 if((string)webSite.Properties["Name"].Value == siteName)

                    return true;

             }

             return false;

          }

          catch

          {

             return false;

          }

      }

      #endregion

       #regionGetNextOpenID 获得一个新的ServerID

       private intGetNextOpenID()

      {

        DirectoryEntry iisComputer = newDirectoryEntry("IIS://localhost/w3svc");

          int nextID = 0;

          foreach (DirectoryEntryiisWebServer in iisComputer.Children)

          {

             string sname = iisWebServer.Name;

             try

             {

                 int name =int.Parse(sname);

                 if (name> nextID)

                {

                    nextID = name;

                }

             }

             catch

             {

             }

          }

          return ++nextID;

      }

      #endregion

#region CreateWebsite 添加网站

       publicstring CreateWebSite(string serverID, string serverComment, stringdefaultVrootPath, string HostName, string IP, stringPort)

      {

          try

          {

             ManagementObject oW3SVC = newManagementObject(_scope, newManagementPath(@"IIsWebService='W3SVC'"), null);

             if (IsWebSiteExists(serverID))

             {

                 return"Site Already Exists...";

             }

             ManagementBaseObject inputParameters =oW3SVC.GetMethodParameters("CreateNewSite");

             ManagementBaseObject[] serverBinding = newManagementBaseObject[1];

             serverBinding[0] = CreateServerBinding(HostName,IP, Port);

             inputParameters["ServerComment"] =serverComment;

             inputParameters["ServerBindings"] =serverBinding;

             inputParameters["PathOfRootVirtualDir"] =defaultVrootPath;

             inputParameters["ServerId"] =serverID;

            

             ManagementBaseObject outParameter =null;

             outParameter =oW3SVC.InvokeMethod("CreateNewSite", inputParameters,null);

            

             // 启动网站

             string serverName = "W3SVC/" +serverID;

             ManagementObject webSite = newManagementObject(_scope, new ManagementPath(@"IIsWebServer='" +serverName + "'"), null);

             webSite.InvokeMethod("Start", null);

             return(string)outParameter.Properties["ReturnValue"].Value;

          }

          catch (Exceptionex)

          {

             return ex.Message;

          }

      }

       publicManagementObject CreateServerBinding(string HostName, string IP,string Port)

      {

          try

          {

             ManagementClass classBinding = newManagementClass(_scope, new ManagementPath("ServerBinding"),null);

             ManagementObject serverBinding =classBinding.CreateInstance();

             serverBinding.Properties["Hostname"].Value =HostName;

             serverBinding.Properties["IP"].Value =IP;

             serverBinding.Properties["Port"].Value =Port;

             serverBinding.Put();

             return serverBinding;

          }

          catch

          {

             return null;

          }

      }

      #endregion

好了,准备工作已经做完,现在开始写最重要的Install方法了

整个方法写完后如下:

#region Install 安装

      ///

       ///安装数据库

      ///

      ///

       publicoverride void Install(IDictionary stateSaver)

      {

          

base.Install(stateSaver);

          dir =this.Context.Parameters["dir"];

          DBName =this.Context.Parameters["DBNAME"].ToString();

          ServerName =this.Context.Parameters["server"].ToString();

          AdminName =this.Context.Parameters["user"].ToString();

          AdminPwd =this.Context.Parameters["pwd"].ToString();

          iis =this.Context.Parameters["iis"].ToString(); ;

          port =this.Context.Parameters["port"].ToString();

         

         //写入获取的安装程序中的变量,此段代码为调试用可以不添加

          this.sqlConn.ConnectionString= "Packet size=4096;User ID=" + AdminName + ";Data Source=" +ServerName + ";Password=" + AdminPwd + ";Persist SecurityInfo=False;Integrated Security=false";

          // 执行SQL 安装数据库可选择时恢复或者时直接创建

         if(!CreateDBAndTable(DBName))

          {

             throw newApplicationException("创建数据库时出现严重错误!");

          }

         

          // 从备份数据库文件恢复数据库

          

          // 添加网站

          Connect();

          //string serverID =GetNextOpenID().ToString();

          //string serverComment =websitenName;

                  //下面的信息为测试,可以自己编写文本框来接收用户输入信息

          string serverID ="5555";

          string serverComment ="cqfeng";

          string defaultVrootPath =this.Context.Parameters["targetdir"];

          if(defaultVrootPath.EndsWith(@""))

          {

             defaultVrootPath = defaultVrootPath.Substring(0,defaultVrootPath.Length-1);

          }

          string HostName ="";

          string IP = "";

          string Port =port;

          string sReturn =CreateWebSite(serverID, serverComment, defaultVrootPath, HostName,IP, Port);

         

          // 修改web.config

          if(!WriteWebConfig())

          {

             throw newApplicationException("设置数据库连接字符串时出现错误");

          }

          // 写注册表

         WriteRegistryKey();

      }

      #endregion

删除时的方法。在本文中未详细操作,比如删除站点,删除数据库等。如果需要,请你自己补足

#region Uninstall 删除

       publicoverride void Uninstall(IDictionary savedState)

      {

          if (savedState ==null)

          {

             throw newApplicationException("未能卸载!");

          }

          else

          {

             base.Uninstall(savedState);

          }

}

      #endregion

编译,然后选择安装,如图:

C#打包--如何用VS2005制作Web安装程序(下)


第一图:

C#打包--如何用VS2005制作Web安装程序(下)

第二图:

C#打包--如何用VS2005制作Web安装程序(下)



第三图:

C#打包--如何用VS2005制作Web安装程序(下)


抱歉,我不知道在这里怎么使登录密码框输入时显示为*号


第四图:

C#打包--如何用VS2005制作Web安装程序(下)

第五图:

C#打包--如何用VS2005制作Web安装程序(下)

安装:

C#打包--如何用VS2005制作Web安装程序(下)

安装完成:

C#打包--如何用VS2005制作Web安装程序(下)

安装后的IIS

C#打包--如何用VS2005制作Web安装程序(下)

安装目录:

C#打包--如何用VS2005制作Web安装程序(下)

安装后的数据库:

C#打包--如何用VS2005制作Web安装程序(下)

至此,一个简单的部署web程序的exe文件已经完成,当然,省略了很多东西,比如,对安装机器的判断(IIS版本,Framework版本,SQLServer版本等),IIS站点属性等设置(默认页面,访问权限,执行权限等),卸载程序时应该删除的东西等等。这些东西,在MSDN里面可以查找到相关说明,如果你需要,只有辛苦一下了,嘿嘿。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值