C# IIS一键部署(微软类库)
前言:
在我们开发一个Web项目的时候,我们需要把项目打包发布到IIS,大概流程是这样的打包项目放到一个目录下,IIS管理器添加项目指定打包好的项目路径等一系列操作,这样会是不是会让大家感觉到很烦?这一系列操作给我的感觉肯定是很烦的点来点去,能不能就是说我点一下能能把我想发布的路径发布出去。答案:能!
在这篇纹章中给大家带来一个IIS一键部署的小工具的实现以及个人的开发思路告诉大家,好了话不多说准备开干!
一、思路:
在本章节中,小编想到的是做成一个配置化发布工具,也就是说通过一个配置文件(json,config)配置好发布的信息,控制台程序运行一下就可以发布出去!
直接上代码和操作图:
打开IIS - 应用程序池 - 右键一个程序池 - 高级设置
打开了之后是不是又很多参数可以配置应用程序池的信息,每个网站都要对应一个程序池这个步骤很关键!
红色箭头是表示,可以在类库中找到对应项的参数配置,方便我们开发!
直接上核心代码了:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 | 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的结构给到大家
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 | { "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文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | <?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= "..\..\..\json\TempConfig.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> |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~