usingMicrosoft.Web.Administration;
usingNewtonsoft.Json;
usingNewtonsoft.Json.Linq;
usingoneKeyDeployment.Common.config;
usingoneKeyDeployment.Model;
usingSystem;
usingSystem.Collections.Generic;
usingSystem.Configuration;
usingSystem.IO;
usingSystem.Linq;
usingSystem.Security.Cryptography.X509Certificates;
usingSystem.ServiceProcess;
usingSystem.Text;
usingSystem.Threading.Tasks;
 
namespaceoneKeyDeployment.Common
{
    /// <summary>
    /// 网站发布帮助类
    /// </summary>
    publicclassPublishWebHelper
    {
        /// <summary>
        /// 执行一键部署(单个网站部署)
        /// </summary>
        /// <returns></returns>
        publicstaticvoidexecute()
        {
            //IIS 配置信息
            varconfig = GetIISConfig();
            varvDir = config.VDir;
            varapp = config.Applications;
            //程序池配置信息
            varpoolsConfig = config.ApplicationPools;
            variismanager = createServerManager(config);
 
            //创建虚拟目录
            if(vDir !=null&& vDir.Count() > 0)
            {
                foreach(vardirinvDir)
                {
                    createVDir(config.WebName, dir.DirName, dir.PhysicalPath, iismanager);
                }
            }
            //创建子程序虚拟目录
            foreach(variteminapp)
            {
                foreach(vardirinitem.VDir)
                {
                    createSubitemVDir(config.WebName, item.Path, dir.DirName, dir.PhysicalPath, iismanager);
                }
            }
            Console.WriteLine("---------------- 程序池 Start ----------------");
            //创建程序池
            foreach(variteminpoolsConfig)
            {
                createApplicationPool(item, iismanager);
            }
            Console.WriteLine("---------------- 程序池 End ----------------");
            //提交保存
            CommitChanges(iismanager);
        }
 
        /// <summary>
        /// 创建应用程序
        /// </summary>
        /// <param name="config"></param>
        /// <returns></returns>
        privatestaticServerManager createServerManager(IISConfig config)
        {
            varApplicationsConfig = config.Applications;
 
            ServiceController service = ServiceController.GetServices("127.0.0.1").FirstOrDefault(x => x.ServiceName =="W3SVC");
 
            if(serviceisnull)
            {
                Console.WriteLine("服务器尚未安装 IIS 服务模块!");
                returnnull;
            }
 
            if(!System.IO.Directory.Exists(config.WebsiteDirectory))
            {
                Console.WriteLine("指定目录不存在!");
                returnnull;
            }
            ServerManager iismanager =newServerManager();
            //判断web应用程序是否存在
            if(iismanager.Sites[config.WebName] !=null)
            {
                ///移除应用程序
                iismanager.Sites.Remove(iismanager.Sites[config.WebName]);
            }
            //建立web应用程序(第二个参数为安装文件的地址)
            varsite = 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(variteminApplicationsConfig)
            {
                varapplication = 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网站的应用程序池
            varwebsite = iismanager.Sites[config.WebName];
            website.Applications["/"].ApplicationPoolName = config.ApplicationPoolName;
            if(!string.IsNullOrEmpty(config.ServerDomainName))
            {
                stringstr = website.Bindings[0].Host.Split(newchar[] {'.'})[0];
                stringbindingInformation = $"*:{config.Port}:{str}{config.ServerDomainName}";
                website.Bindings.Add(bindingInformation,"http");
            }
            returniismanager;
        }
 
        /// <summary>
        /// 提交更改
        /// </summary>
        /// <param name="iismanager"></param>
        privatestaticvoidCommitChanges(ServerManager iismanager)
        {
            //提交更改
            iismanager.CommitChanges();
        }
 
 
        /// <summary>
        /// 创建程序池
        /// </summary>
        /// <param name="pool"></param>
        privatestaticvoidcreateApplicationPool(Model.ApplicationPool poolConfig, ServerManager iismanager)
        {
            //判断应用程序池是否存在
            if(iismanager.ApplicationPools[poolConfig.Name] !=null)
            {
                //移除应用程序池
                iismanager.ApplicationPools.Remove(iismanager.ApplicationPools[poolConfig.Name]);
            }
 
            //cpu
            varcpuConfig = poolConfig.Cpu;
            //回收
            varrecyclingConfig = poolConfig.Recycling;
            //定期重启
            varperiodicRestartConfig = poolConfig.Recycling.PeriodicRestart;
            //进程孤立
            varfailureConfig = poolConfig.Failure;
            //进程模型
            varprocessModelConfig = 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 =newTimeSpan(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(variteminrecyclingConfig.LogEventOnRecycle)
            {
                logEventOnRecycle = logEventOnRecycle | item;
            }
            if(recyclingConfig.LogEventOnRecycle !=null&& recyclingConfig.LogEventOnRecycle.Count() > 0)
                pool.Recycling.LogEventOnRecycle = logEventOnRecycle;
            foreach(variteminperiodicRestartConfig.Schedule)
            {
                pool.Recycling.PeriodicRestart.Schedule.Add(item);//定时回收资源
            }
            pool.Recycling.PeriodicRestart.PrivateMemory = periodicRestartConfig.PrivateMemory;
            pool.Recycling.PeriodicRestart.Time =newTimeSpan(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 =newTimeSpan(00, 00, processModelConfig.PingInterval);
            pool.ProcessModel.PingResponseTime =newTimeSpan(00, 00, processModelConfig.PingResponseTime);
            pool.ProcessModel.IdentityType = processModelConfig.IdentityType;
            pool.ProcessModel.UserName = processModelConfig.UserName;
            pool.ProcessModel.Password = processModelConfig.Password;
            pool.ProcessModel.ShutdownTimeLimit =newTimeSpan(00, 00, processModelConfig.ShutdownTimeLimit);
            pool.ProcessModel.LoadUserProfile = processModelConfig.LoadUserProfile ??false;
            pool.ProcessModel.IdleTimeoutAction = IdleTimeoutAction.Terminate;
            pool.ProcessModel.StartupTimeLimit =newTimeSpan(00, 00, processModelConfig.StartupTimeLimit);
            pool.ProcessModel.PingingEnabled = processModelConfig.PingingEnabled ??false;
            pool.ProcessModel.LogEventOnProcessModel = processModelConfig.LogEventOnProcessModel;
            pool.ProcessModel.IdleTimeout =newTimeSpan(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>
        privatestaticIISConfig GetIISConfig()
        {
            varpath = System.Environment.CurrentDirectory + Config._IISConfigPath;
            using(System.IO.StreamReader file = System.IO.File.OpenText(path))
            {
                using(JsonTextReader reader =newJsonTextReader(file))
                {
                    varo = (JObject)JToken.Readfrom(reader);
                    returno.ToObject<IISConfig>();
                }
            }
        }
 
 
        /// <summary>
        /// 添加虚拟目录
        /// </summary>
        /// <param name="siteName">网站名</param>
        /// <param name="vDirName">目录名</param>
        /// <param name="physicalPath">对应的文件夹路径</param>
        /// <param name="iismanager"></param>
        privatestaticvoidcreateVDir(stringsiteName,stringvDirName,stringphysicalPath, 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>
        privatestaticvoidcreateSubitemVDir(stringsiteName,stringsubitemSiteName,stringvDirName,stringphysicalPath, ServerManager iismanager)
        {
 
            varapp = iismanager.Sites[siteName].Applications["/"+ subitemSiteName];
            if(app ==null)
            {
                return;
            }
            app.VirtualDirectories.Add("/"+ vDirName, physicalPath);
        }
    }
}