C# 远程服务器 创建、修改、删除 应用程序池 网站
首先 C# 操作 站点 需要 引用Microsoft.Web.Administration.dll 文件,创建站点我们一般需要 远程服务的IP,网站名称、端口、物理路径;这里默认网站名称和应用程序池名称一致。
应用程序池默认不启动,应为刚创建站点是没有对应真实的物理文件,修改 队列长度、启动模式、回收时间、最大工作进程, 以及日志路径。修改的时候如果修改站点物理路径的话,我们需要把文件 从旧得目录拷贝到新的目录下,删除站点就比较简单了。
但是站点应用程序池的停止 和启动就比较难搞了,不是调用stop后就马上能停止的,我们需要一个检测状态的机制以及重试机制,如果没有停止 就等待一段时间,因为只有应用程序池完全停止后我们在可以拷贝文件到应用程序目录下;启动也是一样的需要一个 等待 和重试的机制。相关code如下:
#region IIS 操作 /// <summary> /// 创建IIS site /// </summary> /// <param name="serverIP">服务器IP</param> /// <param name="webName">site 名称</param> /// <param name="port">site端口</param> /// <param name="path">site地址</param> void CreateWebSite(string serverIP, string webName, int port, string path) { using (ServerManager sm = ServerManager.OpenRemote(serverIP)) { //创建应用程序池 ApplicationPool appPool = sm.ApplicationPools.FirstOrDefault(x => x.Name == webName); if (appPool == null) { appPool = sm.ApplicationPools.Add(webName); appPool.AutoStart = false; appPool.QueueLength = 10000; appPool.StartMode = StartMode.AlwaysRunning;//启动模式 appPool.Recycling.PeriodicRestart.Time = new TimeSpan();//回收时间间隔 appPool.ProcessModel.IdleTimeout = new TimeSpan();//闲置超时 appPool.ProcessModel.MaxProcesses = 1;//最大工作进程数 } //创建Site Site site = sm.Sites.FirstOrDefault(x => x.Name == webName); if (site == null) { //检查远程文件夹是否存在 不存在创建 string remotePath = PathUtil.GetRemotePath(serverIP, path); if (!Directory.Exists(remotePath)) { Directory.CreateDirectory(remotePath); } site = sm.Sites.Add(webName, path, port); site.ServerAutoStart = true; site.Bindings[0].EndPoint.Port = port; Application root = site.Applications["/"]; root.ApplicationPoolName = webName; root.VirtualDirectories["/"].PhysicalPath = path; root.SetAttributeValue("preloadEnabled", true); /*预加载*/ #region 修改日志路径 if (!string.IsNullOrEmpty(ConfigUtil.IISLog)) { string remoteLog = PathUtil.GetRemotePath(serverIP, ConfigUtil.IISLog); if (!Directory.Exists(remoteLog)) { Directory.CreateDirectory(remoteLog); } site.LogFile.Directory = ConfigUtil.IISLog; string failedLog = Path.Combine(ConfigUtil.IISLog, "FailedReqLogFiles"); if (!Directory.Exists(failedLog)) { Directory.CreateDirectory(failedLog); } site.TraceFailedRequestsLogging.Directory = failedLog; } #endregion } sm.CommitChanges(); } } /// <summary> /// 修改IIS站点名 端口 和路径 /// </summary> /// <param name="serverIP">服务器IP</param> /// <param name="oldWebName">旧的名称</param> /// <param name="newWebName">新的web名称</param> /// <param name="newPort">新的端口</param> /// <param name="newPath">新的路径</param> void ModifyWebSite(string serverIP, string oldWebName, string newWebName, int newPort, string newPath) { using (ServerManager sm = ServerManager.OpenRemote(serverIP)) { //修改应用程序池 ApplicationPool appPool = sm.ApplicationPools.FirstOrDefault(x => x.Name == oldWebName); if (appPool != null && oldWebName != newWebName) { appPool.Name = newWebName; } //修改Site Site site = sm.Sites.FirstOrDefault(x => x.Name == oldWebName); if (site != null) { Application root = site.Applications["/"]; if (oldWebName != newWebName) { site.Name = newWebName; root.ApplicationPoolName = newWebName; } int oldPort = site.Bindings[0].EndPoint.Port; if (oldPort != newPort) {
var binding = site.Bindings[0];
site.Bindings.RemoveAt(0);
site.Bindings.Add($"*:{newPort}:" + binding.Host, binding.Protocol);
} string oldPath = root.VirtualDirectories["/"].PhysicalPath; if (oldPath.ToLower() != newPath.ToLower()) { string remoteOldPath = PathUtil.GetRemotePath(serverIP, oldPath); string remoteNewPath = PathUtil.GetRemotePath(serverIP, newPath); if (!Directory.Exists(remoteNewPath)) { Directory.CreateDirectory(remoteNewPath); } //拷贝文件 CopyFiles(remoteOldPath, remoteNewPath); if (Directory.Exists(remoteOldPath)) { Directory.Delete(remoteOldPath, true); } root.VirtualDirectories["/"].PhysicalPath = newPath; } } #region 修改日志路径 if (!string.IsNullOrEmpty(ConfigUtil.IISLog)) { string remoteLog = PathUtil.GetRemotePath(serverIP, ConfigUtil.IISLog); if (!Directory.Exists(remoteLog)) { Directory.CreateDirectory(remoteLog); } site.LogFile.Directory = ConfigUtil.IISLog; string failedLog = Path.Combine(ConfigUtil.IISLog, "FailedReqLogFiles"); if (!Directory.Exists(failedLog)) { Directory.CreateDirectory(failedLog); } site.TraceFailedRequestsLogging.Directory = failedLog; } #endregion sm.CommitChanges(); } } /// <summary> /// 删除IIS 站点 /// </summary> /// <param name="serverIP">服务器地址</param> /// <param name="webName">站点名</param> void RemoveWebSite(string serverIP, string webName) { string path = string.Empty; using (ServerManager sm = ServerManager.OpenRemote(serverIP)) { //删除应用程序池 ApplicationPool appPool = sm.ApplicationPools.FirstOrDefault(x => x.Name == webName); if (appPool != null) { //appPool.Stop(); sm.ApplicationPools.Remove(appPool); } //删除Site Site site = sm.Sites.FirstOrDefault(x => x.Name == webName); if (site != null) { path = site.Applications["/"].VirtualDirectories["/"].PhysicalPath; sm.Sites.Remove(site); } sm.CommitChanges(); } //删除文件 if (!string.IsNullOrEmpty(path)) { string remotePath = PathUtil.GetRemotePath(serverIP, path); if (Directory.Exists(remotePath)) { Directory.Delete(remotePath, true); } } } /// <summary> /// 在服务器上检查端口是否被其他站点使用 /// </summary> /// <param name="webIP">服务器地址</param> /// <param name="port">端口号</param> /// <param name="webName">站点名</param> /// <returns></returns> bool CheckPortIsUsed(string webIP, string webName, int webPort) { bool exist = false; try { using (ServerManager sm = ServerManager.OpenRemote(webIP)) { List<Site> sites = sm.Sites.ToList(); foreach (Site site in sites) { foreach (var item in site.Bindings) { if (item.EndPoint != null && item.EndPoint.Port == webPort && site.Name != webName) { exist = true; break; } }//end for Bindings }//end for Site } } catch (Exception ex) { throw ex; } return exist; } /// <summary> /// 停止或启动应用程序池 /// </summary> /// <param name="serverIP">远程服务器IP</param> /// <param name="poolNames">应用程序池名称集合</param> /// <param name="stop">true 停止 false 启动</param> public void StopAndStartAppPool(string serverIP, string poolName, bool stop = true) { using (ServerManager sm = ServerManager.OpenRemote(serverIP)) { ApplicationPool pool = sm.ApplicationPools.FirstOrDefault(x => x.Name == poolName); if (pool != null) { StopAndStartAppPool(pool, stop); if (stop) { WaiteAppPoolState(pool, ObjectState.Stopped); } } } } /// <summary> /// 停止或启动应用程序池 /// </summary> /// <param name="pool">应用程序池对象</param> /// <param name="stop">是否是停止</param> void StopAndStartAppPool(ApplicationPool pool, bool stop = true) { Action act = () => { ObjectState poolSate = pool.State; if (stop && (poolSate == ObjectState.Starting || poolSate == ObjectState.Started)) { //如果当前应用程序池是启动或者正在启动状态,调用停止方法 pool.Stop(); } if (!stop && (poolSate == ObjectState.Stopped || poolSate == ObjectState.Stopping)) { pool.Start(); } }; int retryCount = 0; int maxCount = 4; while (pool != null && retryCount <= maxCount) { try { act(); break; } catch (Exception ex) { retryCount++; if (retryCount == maxCount) { throw new Exception($"{(stop ? "停止" : "启动")}启动应用程序池{pool.Name}出错{ex.Message}"); } Thread.Sleep(1000 * 30); } }//end while } /// <summary> /// 检查引用程序池的状态 /// </summary> /// <param name="pool">程序池</param> /// <param name="state">状态</param> void WaiteAppPoolState(ApplicationPool pool, ObjectState state) { int times = 0; while (pool.State != state && times < 50 /*5分钟*/) { //检查应用程序池是否已经停止 Thread.Sleep(1000 * 10); times++; } } /// <summary> /// 获取应用程序池 和站点的状态 /// </summary> /// <param name="serverIP">服务器IP</param> /// <param name="webName">站点名称</param> /// <returns></returns> string GetWebState(string serverIP, string webName) { ObjectState poolState = ObjectState.Unknown; ObjectState siteState = ObjectState.Unknown; using (ServerManager sm = ServerManager.OpenRemote(serverIP)) { //应用程序池 ApplicationPool appPool = sm.ApplicationPools.FirstOrDefault(x => x.Name == webName); if (appPool != null) { poolState = appPool.State; } //Site Site site = sm.Sites.FirstOrDefault(x => x.Name == webName); if (site != null) { siteState = site.State; } } return $"{poolState.ToString()} | {siteState.ToString()}"; } #endregion
public class ConfigUtil { static string _dotNetPath = string.Empty; public static string DotNetPath { get { if (string.IsNullOrEmpty(_dotNetPath)) { string sysDisk = Environment.SystemDirectory.Substring(0, 3); _dotNetPath = sysDisk + @"WINDOWS\Microsoft.NET\Framework\v4.0.30319\InstallUtil.exe";//因为当前用的是4.0的环境 } return _dotNetPath; } } static string _iisLog = string.Empty; public static string IISLog { get { if (string.IsNullOrEmpty(_iisLog)) { _iisLog = ConfigurationManager.AppSettings["IISLog"]; } return _iisLog; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构