WEB项目(B/S系统)打包安装(总结篇)

简介: 原文:WEB项目(B/S系统)打包安装(总结篇) 打包安装程序的制作选择性还很多的,有installshield,wise installer,inno setup这几个做打包安装项目都是很强大的,要搞出界面大气个性化的安装,还是得用这几个才行,我这篇说的是.NET自带的安装项目打包WEB系统的,.NET打包安装项目虽然傻傻的,也比较丑,但是搭建安装项目快速也能满足总体的要求,如果没有足够的时间研究重量级的安装工具,短时间内用.NET自带的安装项目也是一个良好的选择。
原文: WEB项目(B/S系统)打包安装(总结篇)

打包安装程序的制作选择性还很多的,有installshield,wise installer,inno setup这几个做打包安装项目都是很强大的,要搞出界面大气个性化的安装,还是得用这几个才行,我这篇说的是.NET自带的安装项目打包WEB系统的,.NET打包安装项目虽然傻傻的,也比较丑,但是搭建安装项目快速也能满足总体的要求,如果没有足够的时间研究重量级的安装工具,短时间内用.NET自带的安装项目也是一个良好的选择。网上有很多关于用.NET打包WEB项目的文章,大体是那样的,但不是很全面,有个别细节并没有涉及,先说下这个安装打包项目的主要功能:

      一、安装前系统检测

             主要检测SQL SERVER是否安装,站点名称和端口号是否重复等,framework自动检测没有的话先安装,本身自带就有此功能,IIS是必须要求的,不然没法创建站点。

  二、项目文件安装到指定文件夹并根据安装时的数据库配置修改webconfig连接

      三、附加数据库

           打包时可以把mdf文件放到WEB项目文件夹下,生成安装文件时就会自动打包进去,安装时执行附加即可。

      四、注册COM组件(如果项目中涉及到COM的话)

      五、创建WEB站点

      六 、创建虚拟目录

           这里的虚拟目前是根据打包的项目需要进行的,因为有的WEB项目结构比较复杂,比如一个系统除了本身项目的发布文件,还有另外的独立特殊功能的项目作为虚拟目录的形式一起运行,类似于插拔式的插件一样,需要的话直接拷贝到站点下,设置虚拟目录,系统菜单做好链接指向其页面就可以了。

     七、创建桌面快捷方式

           比如可以把系统的登录页面或其它起始页作为安装时指定的快捷方式

     八、项目卸载

          项目的卸载主要包括删除项目文件,卸载附加的数据库,删除站点及桌面快捷方式等

 

       安装WEB项目的前提条件是需要在用户电脑上先安装SQL SERVER数据库(或其它数据库)和IIS信息管理器。

     1)安装项目主要涉及的是安装类里面的操作,包括安装和卸载的方法重写等,安装时需要记录用户通过安装界面输入的信息,这里我们可以用XML文件作为记录配置文件,主要是在卸载的时候需要用到用户输入的相关信息,数据库连接串的记录操作如下:

     

  ///   <summary>
        
///  获取数据库登录连接字符串
        
///   </summary>
        
///   <param name="databasename"> 数据库名称 </param>
        
///   <returns></returns>
         private   string  GetConnectionString( string  databasename)
        {
            
string  ConnStr  =   " server= "   +  Context.Parameters[ " server " ].ToString()  +   " ;database= "   +  ( string .IsNullOrEmpty(databasename)  ?   " master "  : databasename)  +   " ;uid= "   +  Context.Parameters[ " user " ].ToString()  +   " ;pwd= "   +  Context.Parameters[ " pwd " ].ToString();
            
if  ( string .IsNullOrEmpty(databasename))  // 将连接串写入XML文件,供卸载操作时读取
            {
                dbpath 
=  Path.Combine( this .Context.Parameters[ " installdir " ].ToString(),  " dbconfig.xml " );
                OperateXML.UpdateXMLNode(dbpath, 
" ConnString " , ConnStr);
            }
            
else
            {
                dbpath 
=  Path.Combine( this .Context.Parameters[ " installdir " ].ToString(),  " dbconfig.xml " );
                OperateXML.UpdateXMLNode(dbpath, 
" DbName " , databasename);
            }
            
return  ConnStr;
        }

        2)安装检测

          

  ///   <summary>
        
///  判断是否安装了SQL SERVER
        
///   </summary>
        
///   <returns></returns>
         private   bool  ExistSqlServerService()
        {
            
bool  Exist  =   false ;
            ServiceController[] service 
=  ServiceController.GetServices();
            
for  ( int  i  =   0 ; i  <  service.Length; i ++ )
            {
                
if  (service[i].ServiceName.Length  >   5   &&  service[i].ServiceName.Substring( 0 5 ==   " MSSQL " // if (service[i].ServiceName == "MSSQLSERVER")
                {
                    Exist 
=   true ;
                    
break ;
                }
            }
            
return  Exist;
        }

       这里是根据服务名称判断的,如果是SQLSERVER EXPRESS版的话,服务名是MSSQL$EXPRESS,其它的数据库实例也是MSSQL$+实例名

 

  ///   <summary>
        
///  检测IIS及版本号
        
///   </summary>
        
///   <returns></returns>
         public   string  GetIISVerstion()
        {

            RegistryKey key 
=  Registry.LocalMachine.OpenSubKey( @" SOFTWARE\Microsoft\INetStp " );
            
if  (key  ==   null )
                
return   string .Empty;
            
else
                
return  Convert.ToString(key.GetValue( " MajorVersion " ))  +   " . "   +  Convert.ToString(key.GetValue( " MinorVersion " ));

        }
 
 
 
 
 
  string  entPath  =  String.Format( " IIS://{0}/w3svc " " localhost " );

        
///   <summary>
        
///  端口号是否重复
        
///   </summary>
        
///   <returns></returns>
         private   bool  IsExistSitePort()
        {
            
bool  exist  =   false ;
            DirectoryEntry ent 
=  GetDirectoryEntry(entPath);
            
foreach  (DirectoryEntry child  in  ent.Children)
            {
                
if  (child.SchemaClassName  ==   " IIsWebServer " )
                {
                    
if  (child.Properties[ " ServerBindings " ].Value  !=   null   &&  child.Properties[ " ServerBindings " ].Value.ToString().Split( ' : ' ).Length  >   1 )
                    {
                        
if  (child.Properties[ " ServerBindings " ].Value.ToString().Split( ' : ' )[ 1 ==  Context.Parameters[ " siteport " ].ToString())
                        {
                            exist 
=   true ;
                            
break ;
                        }
                    }
                }
            }
            
return  exist;
        }

child.Properties["ServerBindings"].Value 是绑定属性,其实就是下面这个图里的属性

                        

  但是有的站点可能会分配两个端口,child.Properties["ServerBindings"].Value 就是 System.Object[] 字符

  

 

         ///   <summary>
        
///  站点名称是否存在
        
///   </summary>
        
///   <returns></returns>
         private   bool  IsExistSiteName( string  sitename)
        {
            
bool  exist  =   false ;
            
using  (DirectoryEntry root  =   new  DirectoryEntry(entPath))
            {
                
foreach  (DirectoryEntry Child  in  root.Children)
                {
                    
if  (Child.SchemaClassName  ==   " IIsWebServer " )
                    {
                        
string  WName  =  Child.Properties[ " ServerComment " ].Value.ToString();
                        
if  (sitename  ==  WName)
                        {
                            exist 
=   true ;
                            
break ;
                        }
                    }
                }
                root.Close();
            }
            
return  exist;
        }

         3)安装并复制文件

           复制文件的操作在OnBeforeInstall方法中就已经完成,在该方法中可以替换数据库连接字符串操作等。

         

  protected   override   void  OnBeforeInstall(IDictionary savedState)
        {
            
if  (ExistSqlServerService())
            {
                
if  (IsExistSitePort())
                {
                    MessageBox.Show(
" 站点端口号重复 " " 信息提示 " , MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    
return ;
                }
                
if  (IsExistSiteName(Context.Parameters[ " sitename " ].ToString()))
                {
                    MessageBox.Show(
" 站点名称重复 " " 信息提示 " , MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    
return ;
                }
                
base .OnBeforeInstall(savedState);

                unRAR(
" Message.rar " ); //解压文件
                unRAR(
" MoreUpload.rar " );
                

                
string  webconfigpath  =  Path.Combine( this .Context.Parameters[ " installdir " ].ToString(),  " Web.config " );
                
string  webcofnigstring  =  File.ReadAllText(webconfigpath).Replace( " #constring# " , GetConnectionString(Context.Parameters[ " dbname " ].ToString()));
                webcofnigstring 
=  webcofnigstring.Replace( " #siteport# " , Context.Parameters[ " siteport " ].ToString());
                webcofnigstring 
=  webcofnigstring.Replace( " #comConn# " " Provider=SQLOLEDB.1;Persist Security Info=False;User ID= "   +  Context.Parameters[ " user " ].ToString()  +   " ;Password= "   +  Context.Parameters[ " pwd " ].ToString()  +   " ;Initial Catalog= "   +  Context.Parameters[ " dbname " ].ToString()  +   " ;Data Source= "   +  Context.Parameters[ " server " ].ToString());
                File.WriteAllText(webconfigpath, webcofnigstring);

               
  /// /安装IIS
                 // if (string.Empty == GetIISVerstion())
                
// {
                
//     IISInstall(this.Context.Parameters["installdir"].ToString() + "IIS6.0_XPSP3", this.Context.Parameters["installdir"].ToString() + "iis.txt");
                
// }

            }
            
else
            {
                MessageBox.Show(
" 检测到您的电脑没有安装SQL SERVER,无法继续安装此产品 " " 信息提示 " , MessageBoxButtons.OK, MessageBoxIcon.Warning);
                
this .Rollback(savedState);
            }

        }

      上面代码中解压了两个文件,主要是在安装完创建站点时还需要创建虚拟目录。之所以要先压缩放到WEB项目里,是因为生成安装程序时会检测项目的生成是否成功(是否可以不让它检测成功呢? 还不清楚),一般只要我们把发布好的项目COPY到新建项目下就可以,但是独立的项目文件夹有自己独立的bin目录和webconfig文件,是不能混合在一起生成成功的,但是又需要一次完全安装,那么可以先压缩做为WEB项目下的文件,待复制完后再解压。

     4)安装

        

  ///   <summary>
        
///  安装
        
///   </summary>
        
///   <param name="stateSaver"></param>
         public   override   void  Install(IDictionary stateSaver)
        {
            
if  (ExistSqlServerService())
            {
                
if  (IsExistSitePort())
                {
                    MessageBox.Show(
" 站点端口号重复 " " 信息提示 " , MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    
return ;
                }
                
if  (IsExistSiteName(Context.Parameters[ " sitename " ].ToString()))
                {
                    MessageBox.Show(
" 站点名称重复 " " 信息提示 " , MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    
return ;
                }

                
base .Install(stateSaver);

                WriteBat();
                RegisterCom();
                
string  connectionString  =  GetConnectionString( null );
                
try
                {
                    
using  (SqlConnection connection  =   new  SqlConnection(connectionString))
                    {
                        connection.Open();

                        
string  sql  =   " sp_attach_db ' "   +  Context.Parameters[ " dbname " ].ToString()  +   " ',' "   +  Context.Parameters[ " installdir " ].ToString()  +   " App_Data/Db_Data.MDF',' "
                            
+  Context.Parameters[ " installdir " ].ToString()  +   " App_Data/Db_Data_Log.LDF' " ;

                        ExecuteSQL(connection, sql);
                        connection.Close();
                    }

                }
                
catch  (Exception ex)
                {
                    MessageBox.Show(
" 数据库安装失败!\n数据库配置有误,请正确配置信息!\n "   +  ex.Message,  " 出错! " );
                    
this .Rollback(stateSaver);
                    
return ;
                }

                
try
                {
                    CreateDeskTopShortcut();
                    NewWebSiteInfo siteInfo 
=   new  NewWebSiteInfo( string .Empty, Context.Parameters[ " siteport " ].ToString(),  "" , Context.Parameters[ " sitename " ].ToString(), Context.Parameters[ " installdir " ].ToString());
                    CreateNewWebSite(siteInfo);
                    StartWebSite(siteInfo.BindString);


                }
                
catch // (Exception ex)
                {
                    
// MessageBox.Show("创建站点失败!\n" + ex.Message, "出错!");
                    
// this.Rollback(stateSaver);
                     CreateVirWebSite( " Message " , Context.Parameters[ " installdir " ].ToString()  +   " Message " );
                     CreateVirWebSite(
" MoreUpload " , Context.Parameters[ " installdir " ].ToString()  +   " MoreUpload " );
                }
            }
            
else
            {
                MessageBox.Show(
" 检测到您的电脑没有安装SQL SERVER,无法继续安装此产品 " " 信息提示 " , MessageBoxButtons.OK, MessageBoxIcon.Warning);
                
this .Rollback(stateSaver);
            }

        }

        上面创建网站时会抛出一个文件路径的异常,但是网站是创建成功的,也算一个遗留问题,创建好网站后调用CreateVirWebSite方法创建虚拟目录。

       5)安装时用户参数接收

          参数的名称在添加安装项目的视图-》用户界面里填写,如下图:

                        

 

        参数的传递在视图——》自定义操作里面设置,如下图:

         

       在CustomActionData里输入所有需要传递到安装类的参数   /dbname=[DBNAME] /server=[SERVER] /user=[UID] /pwd=[PWD] /sitename=[SITENAME] /siteport=[SITEPORT] /startpage=[STARTPAGE] /shortcutname=[SHORTCUTNAME] /installdir="[TARGETDIR]\" 注意这个格式是固定的,尤其安装路径的参数格式installdir="[TARGETDIR]\"这么写

     同时要说明的是在卸载的CustomActionData属性只需要给出installdir参数,即使给了其它的参数,卸载时也是读取不到的,只能读取到初始的默认值,如果安装过程中用户重新修改了就不行了,安装文件时选择的路径始终能正确读取到,正因为如此在安装时需要把录入的相关信息以XML配置文件的形式记录下来,这样才能保证正确无误的卸载。

        6)卸载

           

///   <summary
         ///  卸载 
        
///   </summary>
        
///   <param name="savedState"></param>
         public   override   void  Uninstall(IDictionary savedState)
        {
            DeleteWebSite(); 
// 删除安装文件前先删除站点,因删除站点时需读取安装文件的配置信息
            dbpath  =  Path.Combine( this .Context.Parameters[ " installdir " ].ToString(),  " dbconfig.xml " );
            
string  connectionString  =  OperateXML.GetXmlNodeValue(dbpath,  " ConnString " );
            
string  dbName  =  OperateXML.GetXmlNodeValue(dbpath,  " DbName " );

            
base .Uninstall(savedState);
            
            
try
            {
                
using  (SqlConnection connection  =   new  SqlConnection(connectionString))
                {
                    connection.Open();
                    
string  sql  =   " if exists(select 1 from master..sysdatabases where name= ' "   +  dbName  +   " ') drop database  "   +  dbName;
                    ExecuteSQL(connection, sql);
                    connection.Close();
                }
                
if  (Directory.Exists(Context.Parameters[ " installdir " ].ToString()  +   " Message " ))
                {
                    Directory.Delete(Context.Parameters[
" installdir " ].ToString()  +   " Message " true );//删除解压产生的文件
                }
                
if  (Directory.Exists(Context.Parameters[ " installdir " ].ToString()  +   " MoreUpload " ))
                {
                    Directory.Delete(Context.Parameters[
" installdir " ].ToString()  +   " MoreUpload " true );
                }

            }
            
catch  (Exception ex)
            {
                MessageBox.Show(
" 卸载失败!\n "   +  ex.Message,  " 信息提示 " , MessageBoxButtons.OK, MessageBoxIcon.Warning);
                
this .Rollback(savedState);
                
return ;
            }

        }

        因为解压产生的文件卸载时不会自动删除,需要单独编写代码删除,这些文件是安装过程中产生的次生文件,它只会自动删除原本WEB项目打包进去的原来文件,至于另外产生的文件
是不会自动删除的。对于解压后的文件进行操作,这里也有个一个必须要注意的地方,就是路径问题,解压产生的次生文件,安装时会读取不到解压后的文件夹路径,事实上文件已经复制解压也完成了,但就是读取不到,对应这种情况办法是建立一个和压缩包一样的空文件夹放到WEB项目里,如果解压后的文件里需要替换webconfig连接串,可以在文件夹里放入Web.xml文件,并设置好要替换的地方,前面说了多个webconfig生成会不成功,这里可以先取名xml,解压后替换连接串再修改文件名OK了。

       7)安装项目工程结构

          新建一个网站或项目,然后添加安装项目和安装程序类库,如下图

            

       虽然是WEB项目打包安装,这里选择安装项目就可以了,并不需要选择Web  安装项目。安装项目属性里的系统必备选择相应的.NET类库,安装时如果没有装framework也会自动引导安装,如下图:

       

 

        生成安装项目时会产生两个执行文件,一个.msi 一个setup.exe,msi是打包生成是安装程序,exe是一个引导安装程序,如果电脑上没有安装framework,那么点击exe运行引导安装,如果原本已经安装了相应的framework,那么随便点击那个安装效果是一样的。

        8)运行效果图

                

          

 

         

 

        

 

            

 

            

             上面原本默认的路径是C:\Program Files\peace\项目信息管理系统\  ,如果一级目录原本存在的话会有一个问题,解压时会找不到压缩文件,文件确实是存在的,但是磁盘根目录下却又可以,可能是调用WinRAR解压读写的权限问题。

              

 

             

 

           

 

                 

 

            

 

                   

 

                  下面两张是桌面的快捷方式和附加的数据库图

                         

 

               卸载时也完全卸载了所有相关的文件和内容。

           9)代码下载

               有些代码没贴出来,直接放到源码里下载去看好了,主要是DBInstaller.cs文件里的代码。

               源码下载:点击下载

目录
相关文章
|
4月前
|
安全 Java API
Java Web 在线商城项目最新技术实操指南帮助开发者高效完成商城项目开发
本项目基于Spring Boot 3.2与Vue 3构建现代化在线商城,涵盖技术选型、核心功能实现、安全控制与容器化部署,助开发者掌握最新Java Web全栈开发实践。
493 1
|
5月前
|
JavaScript Java 微服务
现代化 Java Web 在线商城项目技术方案与实战开发流程及核心功能实现详解
本项目基于Spring Boot 3与Vue 3构建现代化在线商城系统,采用微服务架构,整合Spring Cloud、Redis、MySQL等技术,涵盖用户认证、商品管理、购物车功能,并支持Docker容器化部署与Kubernetes编排。提供完整CI/CD流程,助力高效开发与扩展。
679 64
|
6月前
|
安全 JavaScript Java
java Web 项目完整案例实操指南包含从搭建到部署的详细步骤及热门长尾关键词解析的实操指南
本项目为一个完整的JavaWeb应用案例,采用Spring Boot 3、Vue 3、MySQL、Redis等最新技术栈,涵盖前后端分离架构设计、RESTful API开发、JWT安全认证、Docker容器化部署等内容,适合掌握企业级Web项目全流程开发与部署。
525 0
|
6月前
|
JSON JavaScript 前端开发
实现ROS系统的Websocket传输,向Web应用推送sensor_msgs::Image数据
WebSocket协议具有低延迟和高实时性的特性,适用于实时数据推送。但是,它也依赖于网络条件,因此,在通过WebSocket发送数据时,保证网络稳定性也是重要的。以上步骤为建立基本的WebSocket传输提供了框架,并可以根据实际需求进行调整和优化。
540 0
|
8月前
|
人工智能 安全 程序员
用 Colab 和 ngrok 免费部署你的 Web UI 项目,随时随地访问!
用 Colab 和 ngrok 免费部署你的 Web UI 项目,随时随地访问!
1037 12
|
11月前
|
监控 Linux PHP
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
【02】客户端服务端C语言-go语言-web端PHP语言整合内容发布-优雅草网络设备监控系统-2月12日优雅草简化Centos stream8安装zabbix7教程-本搭建教程非docker搭建教程-优雅草solution
422 20
|
11月前
|
网络协议 Java Shell
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
java spring 项目若依框架启动失败,启动不了服务提示端口8080占用escription: Web server failed to start. Port 8080 was already in use. Action: Identify and stop the process that’s listening on port 8080 or configure this application to listen on another port-优雅草卓伊凡解决方案
763 7
|
3月前
|
算法 Java Go
【GoGin】(1)上手Go Gin 基于Go语言开发的Web框架,本文介绍了各种路由的配置信息;包含各场景下请求参数的基本传入接收
gin 框架中采用的路优酷是基于httprouter做的是一个高性能的 HTTP 请求路由器,适用于 Go 语言。它的设计目标是提供高效的路由匹配和低内存占用,特别适合需要高性能和简单路由的应用场景。
315 4
|
7月前
|
缓存 JavaScript 前端开发
鸿蒙5开发宝藏案例分享---Web开发优化案例分享
本文深入解读鸿蒙官方文档中的 `ArkWeb` 性能优化技巧,从预启动进程到预渲染,涵盖预下载、预连接、预取POST等八大优化策略。通过代码示例详解如何提升Web页面加载速度,助你打造流畅的HarmonyOS应用体验。内容实用,按需选用,让H5页面快到飞起!
|
7月前
|
JavaScript 前端开发 API
鸿蒙5开发宝藏案例分享---Web加载时延优化解析
本文深入解析了鸿蒙开发中Web加载完成时延的优化技巧,结合官方案例与实际代码,助你提升性能。核心内容包括:使用DevEco Profiler和DevTools定位瓶颈、四大优化方向(资源合并、接口预取、图片懒加载、任务拆解)及高频手段总结。同时提供性能优化黄金准则,如首屏资源控制在300KB内、关键接口响应≤200ms等,帮助开发者实现丝般流畅体验。