zoukankan      html  css  js  c++  java
  • C# IIS一键部署(微软类库)

    前言:

      在我们开发一个Web项目的时候,我们需要把项目打包发布到IIS,大概流程是这样的打包项目放到一个目录下,IIS管理器添加项目指定打包好的项目路径等一系列操作,这样会是不是会让大家感觉到很烦?这一系列操作给我的感觉肯定是很烦的点来点去,能不能就是说我点一下能能把我想发布的路径发布出去。答案:能!

      在这篇纹章中给大家带来一个IIS一键部署的小工具的实现以及个人的开发思路告诉大家,好了话不多说准备开干!

    一、思路:

      在本章节中,小编想到的是做成一个配置化发布工具,也就是说通过一个配置文件(json,config)配置好发布的信息,控制台程序运行一下就可以发布出去!

    直接上代码和操作图:

    打开IIS - 应用程序池 - 右键一个程序池 - 高级设置


    打开了之后是不是又很多参数可以配置应用程序池的信息,每个网站都要对应一个程序池这个步骤很关键!

    红色箭头是表示,可以在类库中找到对应项的参数配置,方便我们开发!

    直接上核心代码了:

    using Microsoft.Web.Administration;
    using Newtonsoft.Json;
    using Newtonsoft.Json.Linq;
    using oneKeyDeployment.Common.config;
    using oneKeyDeployment.Model;
    using System;
    using System.Collections.Generic;
    using System.Configuration;
    using System.IO;
    using System.Linq;
    using System.Security.Cryptography.X509Certificates;
    using System.ServiceProcess;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace oneKeyDeployment.Common
    {
        /// <summary>
        /// 网站发布帮助类
        /// </summary>
        public class PublishWebHelper
        {
            /// <summary>
            /// 执行一键部署(单个网站部署)
            /// </summary>
            /// <returns></returns>
            public static void Execute()
            {
                //IIS 配置信息
                var config = GetIISConfig();
                var vDir = config.VDir;
                var app = config.Applications;
                //程序池配置信息
                var poolsConfig = config.ApplicationPools;
                var iismanager = CreateServerManager(config);
    
                //创建虚拟目录
                if (vDir != null && vDir.Count() > 0)
                {
                    foreach (var dir in vDir)
                    {
                        CreateVDir(config.WebName, dir.DirName, dir.PhysicalPath, iismanager);
                    }
                }
                //创建子程序虚拟目录
                foreach (var item in app)
                {
                    foreach (var dir in item.VDir)
                    {
                        CreateSubitemVDir(config.WebName, item.Path, dir.DirName, dir.PhysicalPath, iismanager);
                    }
                }
                Console.WriteLine("---------------- 程序池 Start ----------------");
                //创建程序池
                foreach (var item in poolsConfig)
                {
                    CreateApplicationPool(item, iismanager);
                }
                Console.WriteLine("---------------- 程序池 End ----------------");
                //提交保存
                CommitChanges(iismanager);
            }
    
            /// <summary>
            /// 创建应用程序
            /// </summary>
            /// <param name="config"></param>
            /// <returns></returns>
            private static ServerManager CreateServerManager(IISConfig config)
            {
                var ApplicationsConfig = config.Applications;
    
                ServiceController service = ServiceController.GetServices("127.0.0.1").FirstOrDefault(x => x.ServiceName == "W3SVC");
    
                if (service is null)
                {
                    Console.WriteLine("服务器尚未安装 IIS 服务模块!");
                    return null;
                }
    
                if (!System.IO.Directory.Exists(config.WebsiteDirectory))
                {
                    Console.WriteLine("指定目录不存在!");
                    return null;
                }
                ServerManager iismanager = new ServerManager();
                //判断web应用程序是否存在
                if (iismanager.Sites[config.WebName] != null)
                {
                    ///移除应用程序
                    iismanager.Sites.Remove(iismanager.Sites[config.WebName]);
                }
                //建立web应用程序(第二个参数为安装文件的地址)
                var site = iismanager.Sites.Add(config.WebName, config.WebsiteDirectory, config.Port);
    
                Console.WriteLine("---------------- 主应用程序 Start ----------------");
                Console.WriteLine($"网站名称:{config.ServerDomainName}");
                Console.WriteLine($"端口:{config.Port}");
                Console.WriteLine($"服务器域名:{config.ServerDomainName}");
                Console.WriteLine($"网站目录:{config.WebsiteDirectory}");
                Console.WriteLine($"程序池名称:{config.ApplicationPoolName}");
                Console.WriteLine("---------------- 主应用程序 End ----------------");
    
                Console.WriteLine("---------------- 子程序 Start ----------------");
                //设置子程序 - 应用程序池
                foreach (var item in ApplicationsConfig)
                {
                    var application = site.Applications.Add("/" + item.Path, item.PhysicalPath);
                    application.ApplicationPoolName = item.ApplicationPoolName;
                    Console.WriteLine("****************************** ↓");
                    Console.WriteLine($"子程序路径名称:/{item.Path}");
                    Console.WriteLine($"物理路径:{item.PhysicalPath}");
                }
                Console.WriteLine("---------------- 子程序 End ----------------");
                //设置web网站的应用程序池
                var website = iismanager.Sites[config.WebName];
                website.Applications["/"].ApplicationPoolName = config.ApplicationPoolName;
                if (!string.IsNullOrEmpty(config.ServerDomainName))
                {
                    string str = website.Bindings[0].Host.Split(new char[] { '.' })[0];
                    string bindingInformation = $"*:{config.Port}:{str}{config.ServerDomainName}";
                    website.Bindings.Add(bindingInformation, "http");
                }
                return iismanager;
            }
    
            /// <summary>
            /// 提交更改
            /// </summary>
            /// <param name="iismanager"></param>
            private static void CommitChanges(ServerManager iismanager)
            {
                //提交更改
                iismanager.CommitChanges();
            }
    
    
            /// <summary>
            /// 创建程序池
            /// </summary>
            /// <param name="pool"></param>
            private static void CreateApplicationPool(Model.ApplicationPool poolConfig, ServerManager iismanager)
            {
                //判断应用程序池是否存在
                if (iismanager.ApplicationPools[poolConfig.Name] != null)
                {
                    //移除应用程序池
                    iismanager.ApplicationPools.Remove(iismanager.ApplicationPools[poolConfig.Name]);
                }
    
                //cpu
                var cpuConfig = poolConfig.Cpu;
                //回收
                var recyclingConfig = poolConfig.Recycling;
                //定期重启
                var periodicRestartConfig = poolConfig.Recycling.PeriodicRestart;
                //进程孤立
                var failureConfig = poolConfig.Failure;
                //进程模型
                var processModelConfig = poolConfig.ProcessModel;
    
                Microsoft.Web.Administration.ApplicationPool pool = iismanager.ApplicationPools.Add(poolConfig.Name);
                pool.Name = poolConfig.Name; // 程序池名字
                pool.StartMode = poolConfig.StartMode;//启动模式
                pool.QueueLength = poolConfig.QueueLength;//队列长度
                pool.ManagedRuntimeVersion = poolConfig.ManagedRuntimeVersion;
                pool.Enable32BitAppOnWin64 = pool.Enable32BitAppOnWin64;
                pool.ManagedPipelineMode = ManagedPipelineMode.Integrated; //托管管道模式
                pool.Cpu.Limit = cpuConfig.Limit;//限制最大CPU 50%
                pool.Cpu.Action = cpuConfig.Action;//竞争cpu时限制使用最大cpu 百分比
                pool.Cpu.ResetInterval = new TimeSpan(00, cpuConfig.ResetInterval, 00); //时隔5分钟
                pool.Cpu.SmpAffinitized = cpuConfig.SmpAffinitized ?? false;
                //回收
                pool.Recycling.DisallowRotationOnConfigChange = recyclingConfig.DisallowRotationOnConfigChange ?? true; //发生配置更改时禁止回收
                pool.Recycling.DisallowOverlappingRotation = recyclingConfig.DisallowOverlappingRotation ?? true;//禁用重叠回收
                RecyclingLogEventOnRecycle logEventOnRecycle = RecyclingLogEventOnRecycle.None;
                foreach (var item in recyclingConfig.LogEventOnRecycle)
                {
                    logEventOnRecycle = logEventOnRecycle | item;
                }
                if (recyclingConfig.LogEventOnRecycle != null && recyclingConfig.LogEventOnRecycle.Count() > 0)
                    pool.Recycling.LogEventOnRecycle = logEventOnRecycle;
                foreach (var item in periodicRestartConfig.Schedule)
                {
                    pool.Recycling.PeriodicRestart.Schedule.Add(item);//定时回收资源
                }
                pool.Recycling.PeriodicRestart.PrivateMemory = periodicRestartConfig.PrivateMemory;
                pool.Recycling.PeriodicRestart.Time = new TimeSpan(00, periodicRestartConfig.Time, 00);
                pool.Recycling.PeriodicRestart.Requests = periodicRestartConfig.Requests;
                pool.Recycling.PeriodicRestart.Memory = periodicRestartConfig.Memory;
                //进程孤立
                pool.Failure.OrphanActionParams = failureConfig.OrphanActionParams;
                pool.Failure.OrphanActionExe = failureConfig.OrphanActionExe;
                pool.Failure.OrphanWorkerProcess = failureConfig.OrphanWorkerProcess ?? false;
                //模型
                pool.ProcessModel.PingInterval = new TimeSpan(00, 00, processModelConfig.PingInterval);
                pool.ProcessModel.PingResponseTime = new TimeSpan(00, 00, processModelConfig.PingResponseTime);
                pool.ProcessModel.IdentityType = processModelConfig.IdentityType;
                pool.ProcessModel.UserName = processModelConfig.UserName;
                pool.ProcessModel.Password = processModelConfig.Password;
                pool.ProcessModel.ShutdownTimeLimit = new TimeSpan(00, 00, processModelConfig.ShutdownTimeLimit);
                pool.ProcessModel.LoadUserProfile = processModelConfig.LoadUserProfile ?? false;
                pool.ProcessModel.IdleTimeoutAction = IdleTimeoutAction.Terminate;
                pool.ProcessModel.StartupTimeLimit = new TimeSpan(00, 00, processModelConfig.StartupTimeLimit);
                pool.ProcessModel.PingingEnabled = processModelConfig.PingingEnabled ?? false;
                pool.ProcessModel.LogEventOnProcessModel = processModelConfig.LogEventOnProcessModel;
                pool.ProcessModel.IdleTimeout = new TimeSpan(00, processModelConfig.IdleTimeout, 00);
                pool.ProcessModel.MaxProcesses = processModelConfig.MaxProcesses;
                Console.WriteLine("****************************** ↓");
                Console.WriteLine($"程序池名称:{poolConfig.Name}");
                Console.WriteLine($"队列长度:{poolConfig.QueueLength}");
                Console.WriteLine($"启动模式:{poolConfig.StartMode}");
                Console.WriteLine($"启用32位应用程序:{poolConfig.Enable32BitAppOnWin64}");
                Console.WriteLine($"托管管道模式:{poolConfig.ManagedPipelineMode}");
            }
    
            /// <summary>
            /// 获取IIS配置
            /// </summary>
            /// <returns></returns>
            private static IISConfig GetIISConfig()
            {
                var path = System.Environment.CurrentDirectory + Config._IISConfigPath;
                using (System.IO.StreamReader file = System.IO.File.OpenText(path))
                {
                    using (JsonTextReader reader = new JsonTextReader(file))
                    {
                        var o = (JObject)JToken.ReadFrom(reader);
                        return o.ToObject<IISConfig>();
                    }
                }
            }
    
    
            /// <summary>
            /// 添加虚拟目录
            /// </summary>
            /// <param name="siteName">网站名</param>
            /// <param name="vDirName">目录名</param>
            /// <param name="physicalPath">对应的文件夹路径</param>
            /// <param name="iismanager"></param>
            private static void CreateVDir(string siteName, string vDirName, string physicalPath, ServerManager iismanager)
            {
    
                Site site = iismanager.Sites[siteName];
                if (site == null)
                {
                    return;
                }
                site.Applications["/"].VirtualDirectories.Add("/" + vDirName, physicalPath);
            }
    
            /// <summary>
            /// 添加虚拟目录
            /// </summary>
            /// <param name="siteName">网站名</param>
            /// <param name="vDirName">目录名</param>
            /// <param name="physicalPath">对应的文件夹路径</param>
            /// <param name="iismanager"></param>
            private static void CreateSubitemVDir(string siteName, string subitemSiteName, string vDirName, string physicalPath, ServerManager iismanager)
            {
    
                var app = iismanager.Sites[siteName].Applications["/" + subitemSiteName];
                if (app == null)
                {
                    return;
                }
                app.VirtualDirectories.Add("/" + vDirName, physicalPath);
            }
        }
    }

    小编用的是json文件配置IIS发布的所以这里上个json的结构给到大家

    {
      "WebName": "testName", //网站名称
      "Port": 8020, //端口
      "ServerDomainName": "", //服务器域名
      "WebsiteDirectory": "D:\IIS\TLSC.Admin", //网站目录
      "ApplicationPoolName": "File", //程序池名称
      //虚拟目录没有就默认[]
      "VDir": [],
      //子节点
      "Applications": [
        {
          "Path": "File", //路径名称
          "PhysicalPath": "D:\IIS\TLSC.Admin", //物理路径
          "ApplicationPoolName": "File", //程序池名称
          //虚拟目录没有就默认[]
          "VDir": []
        },
        {
          "Path": "Admin", //路径名称
          "PhysicalPath": "D:\IIS\TLSC.Admin", //物理路径
          "ApplicationPoolName": "Admin", //程序池名称
          //虚拟目录没有就默认[]
          "VDir": []
        }
      ],
      "ApplicationPools": [
        {
          "ManagedRuntimeVersion": "v4.0", //版本编号
          "QueueLength": 1000, //队列长度
          "StartMode": 1, //启动模式
          "Enable32BitAppOnWin64": false, //启用32位应用程序
          "Name": "File", //程序池名称
          "ManagedPipelineMode": 0, //托管管道模式 0 Integrated / 1 Classic
          //CPU
          "Cpu": {
            "Limit": 0, //Limit = 50000 限制最大CPU 50% , 默认为0
            "Action": 3, //限制操作 0 NoAction / 1 KillW3wp / 2 Throttle / 3 ThrottleUnderLoad
            "ResetInterval": 5, //时间间隔(分钟)
            "SmpAffinitized": false //已启用处理器关联
          },
          //回收
          "Recycling": {
            "DisallowRotationOnConfigChange": false, //发生配置更改时禁止回收
            "DisallowOverlappingRotation": false, //禁用重叠回收
            //生成和回收时间日志条目 0 None (所有为false)/ 1 Time / 2 Requests / 4 Schedule / 8 Memory / 16 IsapiUnhealthy / 32 OnDemand/ 64 ConfigChange / 128 PrivateMemory /[] 默认所有true
            "LogEventOnRecycle": [ 2, 3, 4, 5 ],
            "PeriodicRestart": {
              "Time": 50, //固定时间间隔(分钟)
              "Requests": 0, //请求限制 默认为零
              "Memory": 0, //虚拟内存限制(KB)
              "PrivateMemory": 1024000, //专用内存限制(KB)
              //特定时间
              "Schedule": [
                "03:00:00",
                "02:00:00"
              ]
            }
          },
          //进程孤立
          "Failure": {
            "OrphanActionExe": "", //可执行文件
            "OrphanActionParams": "", //可执行文件参数
            "OrphanWorkerProcess": false //已启用
          },
          //进程模型
          "ProcessModel": {
            "PingInterval": 30, //Ping间隔(秒)
            "PingResponseTime": 90, //Ping最大响应时间(秒)
            "IdentityType": 0, //标识 0 LocalSystem , 1 LocalService , 2 NetworkService, 3 SpecificUser, 4 ApplicationPoolIdentity
            "UserName": "", //标识 账号
            "Password": "", //标识 密码
            "ShutdownTimeLimit": 90, //关闭时间限制(秒)
            "LoadUserProfile": true, //加载用户配置文件
            "IdleTimeoutAction": 0, //空闲超时操作 0 Terminate / 1 Suspend
            "StartupTimeLimit": 90, //启动时间限制(秒)
            "PingingEnabled": true, //启用 Ping
            "LogEventOnProcessModel": 1, //生成进程模型事件日志条目-空闲超时已到
            "IdleTimeout": 20, //闲置超时(分钟)
            "MaxProcesses": 1 //最大工作进程数
          }
        }
      ]
    }
    

    json的文件路径也是可配置的,在app.config配置读取json文件

    <?xml version="1.0" encoding="utf-8"?>
    <configuration>
        <startup> 
            <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
        </startup>
      <appSettings>
        <add key="IISConfigPath" value="......jsonTempConfig.json" />
      </appSettings>
      <runtime>
        <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
          <dependentAssembly>
            <assemblyIdentity name="System.Reflection.TypeExtensions" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.1.2.0" newVersion="4.1.2.0" />
          </dependentAssembly>
        </assemblyBinding>
      </runtime>
    </configuration>

    源码链接:https://gitee.com/Ramon-Zeng/oneKeyDeployment

  • 相关阅读:
    四 闭包函数、装饰器
    三 名称空间与作用域
    二 函数对象、函数嵌套
    一 函数定义
    函数路线
    Django_rest_framework分页
    Django Rest framework序列化流程
    Django Rest framework的限流实现流程
    mysql 数据库查看表的信息
    java JDBC编程流程步骤
  • 原文地址:https://www.cnblogs.com/IT-Ramon/p/12673401.html
Copyright © 2011-2022 走看看