web打包和IIS配置

4 篇文章 0 订阅
1 篇文章 0 订阅

关于打包web项目很简单,但是要顺便配置IIS,做到安装完后就能用的话,要重写Installer类的Install方法.

网上找了很多套方案,结果都有问题,东拼西凑折腾好几天终于做出来了.

准备:

1,web发布文件(里面可以放其他东西,不影响,也可以是web发布的文件夹)

2,vs(我是2017,也不影响)

3,要能创建visual studio installer项目,没有这个要在拓展和更新搜索下载,如下图:

废话不多说,开始吧

一:新建web setup安装项目,可以和其他项目不在同目录下,或者干脆新建个解决方案:

 

二:右键解决方案>添加>现有网站>选择web发布文件夹

 

三:新建类库(名字随意)>在类库下新建安装程序类

注意:记得是安装程序类,不是普通的类,

打开类后有单击此处切换到代码视图这个东东,并且自动继承安装类

 [RunInstaller(true)]
 public partial class WebCardInstaller : Installer

配置IIS就在重写这个类的方法里:

public override void Install(IDictionary stateSaver)

 

四:右键安装项目>视图>用户界面>右键Start>添加对话框>选择你要的界面

常用的就是文本框AB,一个用来输入数据库配置,一个IIS配置,一个许可条款(不要也行),

注意:自己添加的框要拖拽到欢迎使用和安装地址之间,要不会有波浪线警告.

分别在文本框AB的属性上设置参数,由于我没在这装数据库,所以就贴IIS的参数吧

注意了:property这个属性很重要,代码区要根据这个读取value里的值和拼接关键字属性字符串,默认全是大写的.

如果只要3个参数,把其中一个visible设为false即可.

数据库类似的,传入必要的服务器名,账号,密码,数据库名即可.

 

五:右键安装项目>视图>文件系统>右键web安装文件夹>添加>项目输出>选择web发布文件夹和刚刚添加的类库

添加类库和发布文件选的方式也不同,还可以直接把发布文件夹整个拖进去,这样只要加类库输出,但是不建议这样,因为拖进去的文件不能操作,删除替换全都不行.

在文件系统的属性界面可以设置IIS的参数,比如默认起始页,读写权限,访问脚本权限等,也可以用代码来设置.

 

六:右键安装项目>视图>启动条件>在IIS Condition的属性上,把启动版本改下

 

七:右键安装项目>视图>自定义操作,在install(安装)再右键添加操作

添加在步骤五添加的主输出(类库)

注意:箭头指向的那个add output可以指定到web项目,据说这样就不用发布文件了,打包的时候会自动提取发布文件,但是我试过,直接把dll文件给打包了...

而且这样搞需要把安装项目和web项目放在同个解决方案.

添加后:

uninstall是卸载,也可以这样搞,但是感觉默认的卸载够用了,就不加了.

关键的来了,还记得在步骤四里设置的属性参数吗?在这需要用到它们来拼接关键字了,格式如下:

/iis=[IISSERVER] /ip=[IP] /port=[PORT] /isname=[ISNAME] /targetdir="[TARGETDIR]\"

中括号里大写的字符是步骤四里的property属性值,小写的是在代码中用来读取的关键字,可以看成是key.

每组关键字有个空格,最后有眼号的是IIS安装路径,眼号不能省略,最后一个是反斜杠 \

如果要装数据库,则数据库界面的属性也要加进来.

选中主输出,切换到属性,贴上上面拼接的关键字:

 

补充下,许可条款那个界面只要在文件系统传入一个文档,用户界面右键条款添加操作,指定文件系统里的文档就行,可有可无的东西就不弄了.

现在,所有能用鼠标点的设置都做完了,下面进入重点---代码.

思路是这样:

把服务器,端口,IP,站点ID等设置成字段,这样值设置一次,参数也不用传来传去弄的眼花.

必要的操作有:判断网站名和端口是否存在,站点ID取最小的,创建快捷方式,记录网站信息

主方法:

 

Context.Parameters就是获取用户输入的参数,
字段:
        private string iis;//服务器
        private string port;//端口
        private string serverID;//站点ID
        private string ip;//IP

        private DirectoryEntry _iisServer;
        private ManagementScope _scope;
        private ConnectionOptions _connection;

 

 

        /// <summary>
        /// 安装设置
        /// </summary>
        /// <param name="stateSaver"></param>
        public override void Install(IDictionary stateSaver)
        {
            base.Install(stateSaver);
            /*/iis=[IISSERVER] /ip=[IP] /port=[PORT] /isname=[ISNAME] /targetdir="[TARGETDIR]\"*/
            ip = Context.Parameters["ip"].ToString();
            iis = Context.Parameters["iis"].ToString();
            port = Context.Parameters["port"].ToString();
            string defaultVrootPath = Context.Parameters["targetdir"];
            serverID = GetNextOpenID().ToString();//获得一个最小ServerID
            string serverComment = Context.Parameters["isname"].ToString();//网站名
            if (IsExistSitePort())//判断端口重复
            {
                throw new Exception("端口号已被占用!");
            }
            Connect();// 连接IIS服务器

            if (defaultVrootPath.EndsWith(@"\"))//检查是否\结尾
            {
                defaultVrootPath = defaultVrootPath.Substring(0, defaultVrootPath.Length - 1);
            }

            string sReturn = CreateWebSite(serverComment, defaultVrootPath);

            string _path = defaultVrootPath + @"\App_Data\";
            SaveLog(_path, serverID, "serverID");//保存网站信息
            SaveLog(_path, port, "port");//保存网站信息
            SaveLog(_path, sReturn, "result");//保存网站信息

            CreateShortcut(port);//创建快捷方式
        }

 

获取最小网站ID是获取IIS虚拟目录下的所有站点ID,一个个比大小,最后返回一个最大的加1

 
/// <summary> /// 获得一个最小ServerID /// </summary> /// <returns></returns> private int GetNextOpenID() { //DirectoryEntry iisComputer = new DirectoryEntry("IIS://localhost/w3svc"); DirectoryEntry iisComputer = new DirectoryEntry("IIS://" + iis + "/w3svc"); int nextID = 0, name = 0; string sname = ""; foreach (DirectoryEntry iisWebServer in iisComputer.Children) { sname = iisWebServer.Name; try { name = int.Parse(sname); if (name > nextID) { nextID = name; } } catch { } } return ++nextID; }

 

 


根据用户输入的端口直接测试连接来判断是否已有

 

 

 

 

        /// <summary>
        /// 端口号是否重复
        /// </summary>
        /// <returns></returns>
        private bool IsExistSitePort()
        {
            Process p = new Process();
            p.StartInfo = new ProcessStartInfo("netstat", "-a");
            p.StartInfo.CreateNoWindow = true;
            p.StartInfo.UseShellExecute = false;
            p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
            p.StartInfo.RedirectStandardOutput = true;
            p.Start();
            string result = p.StandardOutput.ReadToEnd();
            if (result.IndexOf(Environment.MachineName.ToLower() + ":" + port) >= 0)
            {
                //端口被占用
                return true;
            }

            else
            {
                return false;
            }
        }


添加网站时,主要设置网站的属性,注意大小写

 

 

 

 

        /// <summary>
        /// 添加网站
        /// </summary>
        /// <param name="serverComment"></param>
        /// <param name="defaultVrootPath"></param>
        /// <param name="HostName"></param>
        /// <returns></returns>
        private string CreateWebSite(string serverComment, string defaultVrootPath)
        {
            try
            {
                ManagementObject oW3SVC = new ManagementObject(_scope, new ManagementPath(@"IIsWebService='W3SVC'"), null);

                if (IsWebSiteExists(serverID))//判断同名网站
                {
                    throw new Exception("已有同名网站");
                }
                ManagementBaseObject inputParameters = oW3SVC.GetMethodParameters("CreateNewSite");
                ManagementBaseObject[] serverBinding = new ManagementBaseObject[1];

                serverBinding[0] = CreateServerBinding();//绑定IP地址和端口
                inputParameters["ServerComment"] = serverComment;//网站名
                inputParameters["ServerBindings"] = serverBinding;//网站绑定的数据(IP和端口)
                inputParameters["PathOfRootVirtualDir"] = defaultVrootPath;//安装路径
                inputParameters["ServerId"] = serverID;//网站ID

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

                // 启动网站
                string serverName = "W3SVC/" + serverID;
                ManagementObject webSite = new ManagementObject(_scope, new ManagementPath(@"IIsWebServer='" + serverName + "'"), null);
                webSite.InvokeMethod("Start", null);

                // 网站属性设置
                DirectoryEntry virtualDirectory = (DirectoryEntry)webSite.InvokeMethod("Create", new object[] { "IIsWebVirtualDir", "Root" });
                virtualDirectory.CommitChanges();//保存
                virtualDirectory.Properties["AccessExecute"][0] = false;//可执行文件
                virtualDirectory.Properties["AccessScript"][0] = true;// 可访问脚本
                virtualDirectory.Properties["EnableDefaultDoc"][0] = true;
                virtualDirectory.Properties["DefaultDoc"][0] = "Login.aspx";//默认开打文件
                virtualDirectory.CommitChanges();//保存
                virtualDirectory.Properties["AccessRead"][0] = true;// 读取
                virtualDirectory.Properties["AccessWrite"][0] = true;// 写入
                virtualDirectory.Properties["ContentIndexed"][0] = true;// 资源索引
                virtualDirectory.Properties["AppIsolated"][0] = 2;// 值 0 表示应用程序在进程内运行,值 1 表示进程外,值 2 表示进程池
                virtualDirectory.CommitChanges();//保存

                virtualDirectory.Invoke("AppCreate", new object[] { 2 });
                virtualDirectory.CommitChanges();//保存

                return (string)outParameter.Properties["ReturnValue"].Value;
            }
            catch (Exception ex)
            {
                return ex.Message;
            }
        }

        /// <summary>
        /// 判断网站是否已经存在
        /// </summary>
        /// <param name="serverID"></param>
        /// <returns></returns>
        private bool IsWebSiteExists(string serverID)
        {
            try
            {
                string siteName = "W3SVC/" + serverID;
                ManagementObjectSearcher searcher = new ManagementObjectSearcher(_scope, new ObjectQuery("SELECT * FROM IIsWebServer"), null);
                ManagementObjectCollection webSites = searcher.Get();

                foreach (ManagementObject webSite in webSites)
                {
                    if ((string)webSite.Properties["Name"].Value == siteName)
                        return true;
                }
                return false;
            }
            catch
            {
                return false;
            }
        }


网站绑定注意了,

Hostname是站点名称,一般放空

 

 

        /// <summary>
        /// 网站绑定,绑定IP地址和端口
        /// </summary>
        /// <param name="HostName"></param>
        /// <returns></returns>
        private ManagementObject CreateServerBinding()
        {
            try
            {
                ManagementClass classBinding = new ManagementClass(_scope, new ManagementPath("ServerBinding"), null);
                ManagementObject serverBinding = classBinding.CreateInstance();
                serverBinding.Properties["Hostname"].Value = "";
                serverBinding.Properties["IP"].Value = ip;
                serverBinding.Properties["Port"].Value = port;
                serverBinding.Put();//提交更改
                return serverBinding;
            }
            catch
            {
                return null;
            }
        }


最后是创建快捷方式和保存网站信息:

 

 

 

 

        /// <summary>
        /// 创建快捷方式
        /// </summary>
        /// <param name="Port">端口</param>
        private void CreateShortcut(string Port)
        {
            //获取软件安装的物理目录
            //string urlpath = this.Context.Parameters["targetdir"];
            if (Port != "80")
            {
                string URL = "http://" + ip + ":" + Port + "/Login.aspx";
                string DeskPhath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
                //创建URL快捷方式(文件)
                DeskPhath = DeskPhath + "\\" + "你的名字.url";
                StreamWriter sw = new StreamWriter(File.Open(DeskPhath, FileMode.Create, FileAccess.ReadWrite));
                sw.WriteLine("[DEFAULT]");
                sw.WriteLine("BASEURL=" + URL);
                sw.WriteLine("[InternetShortcut]");
                sw.WriteLine("URL=" + URL);
                //sw.WriteLine("IconFile=" + SetupPath + "\\park.ico");
                // sw.WriteLine("IconIndex=0");
                sw.Flush();
                sw.Close();
            }
        }

        /// <summary>
        /// 保存网站信息
        /// </summary>
        /// <param name="path"></param>
        private void SaveLog(string path, string data, string name)
        {
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }
            path = path + name + ".txt";

            using (FileStream fs = new FileStream(path, FileMode.OpenOrCreate, FileAccess.ReadWrite))
            {
                StreamWriter sw = new StreamWriter(fs);
                sw.WriteLine(data);
                sw.Flush();
                sw.Close();
            }
        }

问我为什么不用xml?因为TXT文件代码更少大笑
 

 

最后右键安装项目,重新生成,然后在debug下会生成2安装文件,双击就能装了.

 

补充下:

因为项目需要,所以把安装数据库的功能搬出来了,就说下我的思路吧.

用winform来安装,

根据用户输入的数据生成SQL创建数据库语句,

把语句连接到数据库执行下就行,

如果创建数据库同时还要创建表和存储过程什么的,建议把数据库内容做成.sql格式的脚本,

先建库,接着use 数据库 go,再执行脚本,

注意:脚本里不能有建库语句,因为数据库执行是一次性加载,一次性执行的,而且GO必须单独一行,所以构建语句要注意.

安装数据库程序建议做成在网站根目录下执行,脚本也放那,这样可以同时读取脚本和web.config文件(读取当前目录文件).

创建好数据库后还要改web.config文件,用xml来操作,这样网站就和数据库对接了.

补个坑,创建安装项目的时候默认启动条件会选本机的最高版本,在没有安装相应版本的电脑安装会报错,我在这坑里趟了半天,差点怀疑人生,跟改IIS一样

右键安装项目,视图,启动条件,改.NET版本

end.

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值