C#操作IIS服务
从事BS开发到程序猿应该都使用过IIS部署web系统,我也部署过很多次,最近写了一个小程序一键部署web系统,下面分享一下我到实现过程。
1.创建对象,其中包含了一般我们站点部署时设置的参数作为它的属性和字段
public class WebSiteInfo { //站点设置参数 public string hostIp { get; set; } //主机ip public string porNum { get; set; } //端口号 public string hostName { get; set; }//主机名 public string webName { get; set; } //网站名 public string appName { get; set; } //应用程序池 public string webPath { get; set; } //物理路径 public string visualName { get; set; } //虚拟目录名称 public string visualPath { get; set; }//虚拟目录 public Dictionary<string, string> newMimeType { get; set; }//需要新添加mime类型 public autherRight autherRight { get; set; }//身份验证模式 public string defoultPage { get; set; }//默认文档 public ManagedPipelineMode CXCMS { get; set; }//程序池模式(0:集成;1:经典) public string CXCBS { get; set; }//程序池标识 public bool Is32 { get; set; }//是否32位应用程序 public int SiteType { get; set; }// 站点类型(0:虚拟目录;1:应用程序) public string UserName { get; set; }//用户名称 public string Password { get; set; }//用户密码 }
2.添加引用
using Microsoft.Web.Administration; // ServerManger类所属命名空间 using NetFwTypeLib; // 添加引用-COM-搜索NetFwTypeLib(当防火墙打开时,添加入站规则)using System.Net; using System.Net.NetworkInformation; using System.ServiceProcess; // 设置文件安全权限类所属命名空间
3.应用程序池操作
/// <summary> /// 获取所有IIS站点 /// </summary> /// <returns></returns> public SiteCollection GetAllSite() { var manager = new ServerManager(); SiteCollection sites = manager.Sites; return sites; }
/// <summary> /// 创建应用程序池 /// </summary> /// <param name="poolName">应用程序池名称</param> /// <param name="enable32BitOn64">是否启用32位应用程序</param> /// <param name="runtimeVersion">CLR版本</param> /// <param name="mode">经典模式或者集成模式</param> public bool CreateAppPool(string poolName, bool enable32BitOn64 = true, string runtimeVersion = "v4.0", bool autoStart = true, ManagedPipelineMode mode = ManagedPipelineMode.Integrated) { try { using (var serverManager = new ServerManager()) { if (serverManager.ApplicationPools[poolName] != null) { return false; } ApplicationPool newPool = serverManager.ApplicationPools.Add(poolName); newPool.ManagedRuntimeVersion = runtimeVersion; // .Net运行版本 newPool.Enable32BitAppOnWin64 = enable32BitOn64; // 是否32位应用程序 newPool.ManagedPipelineMode = mode; // 集成/经典 newPool.AutoStart = autoStart; // 自动启动 // 修改程序集标识 newPool.ProcessModel.IdentityType = ProcessModelIdentityType.SpecificUser; newPool.ProcessModel.UserName = "Administrator"; newPool.ProcessModel.Password = "tlh"; serverManager.CommitChanges(); return true; } } catch (Exception) { return false; } }
/// <summary> /// 删除应用程序池 /// </summary> /// <param name="poolName">应用程序池名字</param> /// <returns></returns> public bool DeleteAppPool(string poolName) { using (var serverManager = new ServerManager()) { var poolObj = serverManager.ApplicationPools[poolName]; if (poolObj != null) { serverManager.ApplicationPools.Remove(poolObj); } serverManager.CommitChanges(); return true; } }
/// <summary> /// 根据应用程序池名称判断应用程序池是否存在 /// </summary> /// <param name="poolName"></param> /// <returns></returns> public bool IsAppPoolExisted(string poolName) { using (var serverManager = new ServerManager()) { var poolObj = serverManager.ApplicationPools[poolName]; if (poolObj == null) { return false; } return true; } }
4.端口操作
/// <summary> /// 判断端口是否被占用 /// </summary> /// <param name="port"></param> /// <returns></returns> public bool IsPortUsing(int port) { bool inUse = false; IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties(); IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners(); foreach (IPEndPoint endPoint in ipEndPoints) { if (endPoint.Port == port) { inUse = true; break; } } return inUse; }
5.站点操作
/// <summary> /// 获取所有的站点 /// </summary> /// <returns></returns> public List<string> GetAllSites() { using (ServerManager serverManager = new ServerManager()) { return serverManager.Sites.Select(it => it.Name).ToList(); } }
/// <summary> /// 创建站点 /// </summary> /// <param name="siteName">站点名称</param> /// <param name="path">站点路径</param> /// <param name="port">端口</param> /// <param name="host">主机(*)</param> /// <param name="requestType">请求类型:http或者https</param> public bool CreateSite(WebSiteInfo webSiteInfo, ref int type) { try { using (var serverManager = new ServerManager()) { var sites = serverManager.Sites; if (sites[webSiteInfo.webName] != null) {// 如果站点存在则删除 DeleteSite(webSiteInfo.webName); } /* 是否存在指定端口的网站 * 如果存在则在指定端口的站点下面创建应用程序 * 否则创建站点 */ bool flag = false; foreach (var site in sites) { // 获取站点端口号 string tempPort = site.Bindings[0].BindingInformation.Split(':')[1]; if (tempPort == webSiteInfo.porNum) { if (webSiteInfo.SiteType == 1) { // 创建应用程序 Application app = site.Applications.Add("/" + webSiteInfo.webName, webSiteInfo.webPath); app.ApplicationPoolName = webSiteInfo.webName; // 创建虚拟目录 VirtualDirectory virtualDic = app.VirtualDirectories.Add("/" + webSiteInfo.visualName, webSiteInfo.visualPath); if (!string.IsNullOrEmpty(webSiteInfo.UserName) && !string.IsNullOrEmpty(webSiteInfo.Password)) { virtualDic.UserName = webSiteInfo.UserName; virtualDic.Password = webSiteInfo.Password; } } else { // 创建虚拟目录 Application app = site.Applications.First(); VirtualDirectory virtualDic = app.VirtualDirectories.Add("/" + webSiteInfo.webName, webSiteInfo.webPath); app.ApplicationPoolName = webSiteInfo.webName; if (!string.IsNullOrEmpty(webSiteInfo.UserName) && !string.IsNullOrEmpty(webSiteInfo.Password)) { virtualDic.UserName = webSiteInfo.UserName; virtualDic.Password = webSiteInfo.Password; } } flag = true; type = 0; break; } } if (!flag) { var site = sites.Add(webSiteInfo.webName, webSiteInfo.webPath, int.Parse(webSiteInfo.porNum)); //var site = sites.Add(siteName, requestType, host + ":" + port + ":", path); //绑定程序池 site.ApplicationDefaults.ApplicationPoolName = webSiteInfo.webName; type = 1; } serverManager.CommitChanges(); } return true; } catch (Exception ex) { return false; } }
/// <summary> /// 获取站点 /// </summary> /// <param name="serverManager"></param> /// <param name="siteName"></param> /// <returns></returns> private Site GetSite(ServerManager serverManager, string siteName) { return serverManager.Sites[siteName]; }
/// <summary> /// 判断站点是否存在 /// </summary> /// <param name="siteName"></param> /// <returns></returns> public bool IsSiteExisted(string siteName) { using (var serverManager = new ServerManager()) { if (serverManager.Sites[siteName] == null) { return false; } return true; } }
/// <summary> /// 删除站点 /// </summary> /// <param name="sitename">站点名称</param> /// <returns></returns> public bool DeleteSite(string sitename) { using (var serverManager = new ServerManager()) { var siteObj = serverManager.Sites[sitename]; if (siteObj != null) { serverManager.Sites.Remove(siteObj); } serverManager.CommitChanges(); return true; } }
6.IIS操作
/// <summary> /// 判断IIS服务器是否存在 /// </summary> /// <returns></returns> public bool IsIISExist() { return ExistService("W3SVC"); } /// <summary> /// 判断IIS服务器是否存在 /// </summary> /// <returns></returns> public bool ExistService(string serviceName) { var services = ServiceController.GetServices(); return services.Count(it => it.ServiceName.Equals(serviceName, StringComparison.Ordinal)) > 0; } /// <summary> /// 判断IIS服务器是否在运行 /// </summary> /// <returns></returns> public bool IsIISRunning() { var services = ServiceController.GetServices(); return services.Count(it => it.ServiceName == "W3SVC" && it.Status == ServiceControllerStatus.Running) > 0; }
7.入站规则
/// <summary> /// 添加防火墙例外端口 /// </summary> /// <param name="name">名称</param> /// <param name="port">端口</param> /// <param name="protocol">协议(TCP、UDP)</param> public bool AddInRules(string name, int port, string protocol) { //创建防火墙策略类的实例 INetFwPolicy2 policy2 = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); //检查是否有同名规则 foreach (INetFwRule item in policy2.Rules) { if (item.Name == name) { return false; } } INetFwRule rule = (INetFwRule)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwRule")); //为规则添加名称 rule.Name = name; //为规则添加描述 rule.Description = "禁止程序访问非指定端口"; //选择入站规则还是出站规则,IN为入站,OUT为出站 rule.Direction = NET_FW_RULE_DIRECTION_.NET_FW_RULE_DIR_IN; //为规则添加协议类型 rule.Protocol = (int)NET_FW_IP_PROTOCOL_.NET_FW_IP_PROTOCOL_TCP; //为规则添加本地端口 rule.LocalPorts = port.ToString(); //为规则添加配置文件类型 rule.Profiles = (int)NET_FW_PROFILE_TYPE2_.NET_FW_PROFILE2_ALL; //设置规则是阻止还是允许(ALLOW=允许,BLOCK=阻止) rule.Action = NET_FW_ACTION_.NET_FW_ACTION_ALLOW; //分组名 rule.Grouping = ""; rule.InterfaceTypes = "All"; //是否启用规则 rule.Enabled = true; try { //添加规则到防火墙策略 policy2.Rules.Add(rule); } catch (Exception e) { return false; } return true; }
/// <summary> /// 删除防火墙例外端口 /// </summary> /// <param name="ports">端口</param> /// <param name="protocol">协议(TCP、UDP)</param> public bool DeleteInRules(string ports, string protocol) { //创建防火墙策略类的实例 INetFwPolicy2 policy2 = (INetFwPolicy2)Activator.CreateInstance(Type.GetTypeFromProgID("HNetCfg.FwPolicy2")); //string ruleName = System.IO.Path.GetFileNameWithoutExtension(appPath); try { //根据规则名称移除规则 policy2.Rules.Remove(ports); } catch (Exception e) { return false; } return true; }
8.自动创建站点
/// <summary> /// 创建站点 /// </summary> /// <param name="webSiteInfo"></param> private void CreateSite(WebSiteInfo webSiteInfo) { var iisBll = new IISHelper(); string websiteName = webSiteInfo.webName; string websitePath = webSiteInfo.webPath;//生成站点时绑定的文件物理路径 int portNumber = int.Parse(webSiteInfo.porNum);//端口 try { #region 服务器判断 if (!iisBll.IsIISExist()) { MessageBox.Show("请检查IIS服务器服务是否存在!"); return; } if (!iisBll.IsIISRunning()) { MessageBox.Show("请检查IIS服务器服务是否在运行!"); return; } #endregion #region 生成站点 //创建应用程序池 if (!iisBll.CreateAppPool(websiteName,webSiteInfo.Is32,"v4.0", true, webSiteInfo.CXCMS)) { } int type = 0;// 0:应用程序;1:站点 //创建站点 if (!iisBll.CreateSite(webSiteInfo, ref type)) { //删除应用程序池 if (iisBll.IsAppPoolExisted(websiteName)) { iisBll.DeleteAppPool(websiteName); } MessageBox.Show("创建站点失败!"); return; } #endregion //添加入站规则(防火墙打开时要添加) iisBll.AddInRules(portNumber.ToString(), portNumber, "TCP"); msg.Text = "请在浏览器上输入服务器的IP和端口"; txtSiteInfo.Text = "http://" + webSiteInfo.hostIp + ":" + webSiteInfo.porNum; if (type == 0) { txtSiteInfo.Text += "/" + webSiteInfo.webName + ""; } MessageBox.Show("创建站点成功!"); } catch (Exception) { MessageBox.Show("catch报错!"); } }
9.因为虚拟目录一般用来上传文件使用,需要比较多的剩余空间,就想着能不能找到本机所有的盘符,将虚拟目录部署到剩余空间最大的盘符里,代码如下:
/// <summary> /// 获取本机盘符空间信息 /// </summary> public class HardDiskPartitionHelper { /// <summary> /// 处理Double值,精确到小数点后几位 /// </summary> /// <param name="_value">值</param> /// <param name="Length">精确到小数点后几位</param> /// <returns>返回值</returns> public static double ManagerDoubleValue(double _value, int Length) { if (Length < 0) { Length = 0; } return System.Math.Round(_value, Length); } /// <summary> /// 获取硬盘上所有的盘符空间信息列表 /// </summary> /// <returns></returns> public static List<HardDiskPartition> GetDiskListInfo() { List<HardDiskPartition> list = null; //指定分区的容量信息 try { SelectQuery selectQuery = new SelectQuery("select * from win32_logicaldisk"); ManagementObjectSearcher searcher = new ManagementObjectSearcher(selectQuery); ManagementObjectCollection diskcollection = searcher.Get(); if (diskcollection != null && diskcollection.Count > 0) { list = new List<HardDiskPartition>(); HardDiskPartition harddisk = null; foreach (ManagementObject disk in searcher.Get()) { int nType = Convert.ToInt32(disk["DriveType"]); if (nType != Convert.ToInt32(DriveType.Fixed)) { continue; } else { harddisk = new HardDiskPartition(); harddisk.FreeSpace = Convert.ToDouble(disk["FreeSpace"]) / (1024 * 1024 * 1024); harddisk.SumSpace = Convert.ToDouble(disk["Size"]) / (1024 * 1024 * 1024); harddisk.PartitionName = disk["DeviceID"].ToString(); list.Add(harddisk); } } } } catch (Exception) { } return list; } /// <summary> /// 找到剩余空间最大的盘符,在该盘符下创建指定目录 /// </summary> /// <param name="directoryName"></param> /// <returns></returns> public static string GetDirectory_FreeSpace_Max(string directoryName) { string path = "C:\\"; try { string partitionName_Max = ""; // 找到剩余空间最大的盘符 double maxFreeSpace = 0; // 剩余空间 List<HardDiskPartition> listInfo = HardDiskPartitionHelper.GetDiskListInfo(); if (listInfo != null && listInfo.Count > 0) { foreach (HardDiskPartition disk in listInfo) { if (disk.FreeSpace > maxFreeSpace) { maxFreeSpace = disk.FreeSpace; partitionName_Max = disk.PartitionName; } } } path = partitionName_Max + "\\" + directoryName; if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } } catch (Exception ex) { throw ex; } return path; } }