设为首页 收藏本站
查看: 1514|回复: 0

[经验分享] 使用C#控制IIS服务器

[复制链接]

尚未签到

发表于 2018-12-8 10:39:13 | 显示全部楼层 |阅读模式
  我们可以很方便地使用Windows提供的IIS管理器来管理IIS服务器,但有的时候,我们需要通过程序来对IIS实现自动的管理和控制。这篇文章将会介绍使用C#管理控制IIS网站的方法,并在给出一份可用的源码及其编译出来的DLL。
  需要注明的是,本文中给出的方法及源码,都是针对IIS6.0及以上版本。Windows XP中的IIS版本为IIS5.1,如果使用本文提供的方法,可能会出现一些问题。
  版权声明:
  IISManager 由 luckzj 开发,任何人在不将其用于商业用途的前提下,都可以免费学习和使用IISManage。如果在学习使用此程序的过程中,遇到任何问题,都可以给我发email,或者直接访问本站 http://soft-bin.com 与我联系。
  下载IISManager
  目前IISManager只支持针对Website的操作,但在后续,我将完善IISManager,使之可以对IIS进行全面的控制。
  我们的介绍将从Active Directory Service开始
  Active Directory Service
  我们使用C#控制IIS,需要使用Active Directory Service,关于ADS的概念我这里我不作过多讨论,网上有很多相关资料。我只介绍如何使用它。
  首先我们需要添加对 System.DirectoryServices 的引用。之后需要在cs文件中引入 System.DirectoryServices 名字空间。
  我们主要使用到的类是DirectoryEntry。我们可以将一个 DirectoryEntry 看作一个节点,每个节点都有其类型,被成为SchemaClass。这个节点会有其属性集合 Properties,方法以及其子节点集合 Children。 我们可以使用 DirectoryEntry 的 Properties访问节点的属性,使用Invoke 方法来调用这个节点上的方法。
  DirectoryEntry 类的构造函数,可以接收一个参数,这个参数为ADS节点的名称。我们将IIS节点的名称作为参数,构造一个DirectoryEntry 的实例,就可以对IIS节点进行访问了。
  使用DirectoryEntry打开IIS网站
  我们可以使用以下方式构造一个DirectroyEntry的实例以使用IIS的目录服务:
  DirectoryEntry Services = new DirectoryEntry("IIS://localhost/W3SVC");
  “IIS://localhost/W3SVC” 即是IIS的目录服务的名称。在创建了这个实例后,我们就可以使用IIS目录服务。
  上面的代码只是打开了IIS目录服务的根节点,各个网站就在这个根节点上,我们需要寻找到我们想要的网站。
  private DirectroyEntry websiteEntry = null;
  internal const string IIsWebServer = "IIsWebServer";
  protected IISWebsite(DirectoryEntry Server)
  {
  websiteEntry = Server;
  }
  public static IISWebsite OpenWebsite(string name)
  {
  // get directory service
  DirectoryEntry Services = new DirectoryEntry("IIS://localhost/W3SVC");
  IEnumerator ie = Services.Children.GetEnumerator();
  DirectoryEntry Server = null;
  // find iis website
  while (ie.MoveNext())
  {
  Server = (DirectoryEntry)ie.Current;
  if (Server.SchemaClassName == IIsWebServer)
  {
  // "ServerComment" means name
  if (Server.Properties["ServerComment"][0].ToString() == name)
  {
  return new IISWebsite(Server);
  break;
  }
  }
  }
  return null;
  }
  我创建了类 IISWebsite 表示网站,用以控制IIS网站,使用其静态方法 IISWebsite.OpenWebsite()可以返回一个此类的实例。
  DirectoryEntry.SchemaClassName 即代表节点的类型,我们需要查找类型为 IIsWebServer 的节点。 IIsWebServer 类型即IIS网站类型。
  我们要在众多的IIS网站中查找名称为name的网站,而网站的名称保存在 DirectroyEntry.Properties["ServerComment"]中。DirectoryEntry的每一个属性又是一个集合,我们可以使用foreach语句来遍历这个属性集合,但对于网站的名称,则没有必要这么做,我们知道DirectoryEntry.Properties["ServerComment"][0]就是网站的名称。
  创建网站
  创建网站即是向IIS目录服务的根节点添加一个新的节点。我先列出创建新网站的源码,其后对源码进行详细讲解。
  ///
  /// create a new website
  ///
  /// website name
  /// website port
  /// root path
  ///
  public static IISWebsite CreateWebsite(string name, int port, string rootPath, string appPool)
  {
  // validate root path
  if (System.IO.Directory.Exists(rootPath) == false)
  {
  throw new DirNotFoundException(rootPath);
  }
  // get directory service
  DirectoryEntry Services = new DirectoryEntry("IIS://localhost/W3SVC");
  // get server name (index)
  int index = 0;
  foreach (DirectoryEntry server in Services.Children)
  {
  if (server.SchemaClassName == "IIsWebServer")
  {
  if (server.Properties["ServerComment"][0].ToString() == name)
  {
  throw new Exception("website:" + name + " already exsit.");
  }
  if (Convert.ToInt32(server.Name) > index)
  {
  index = Convert.ToInt32(server.Name);
  }
  }
  }
  index++; // new index created
  // create website
  DirectoryEntry Server = Services.Children.Add(index.ToString(), IIsWebServer);
  Server.Properties["ServerComment"].Clear();
  Server.Properties["ServerComment"].Add(name);
  Server.Properties["Serverbindings"].Clear();
  Server.Properties["Serverbindings"].Add(":" + port + ":");
  // create ROOT for website
  DirectoryEntry root = Server.Children.Add("ROOT", IISWebVirturalDir.IIsVirtualDir);
  root.Properties["path"].Clear();
  root.Properties["path"].Add(rootPath);
  // create application
  if (string.IsNullOrEmpty(appPool))
  {
  root.Invoke("appCreate", 0);
  }
  else
  {
  // use application pool
  root.Invoke("appCreate3", 0, appPool, true);
  }
  root.Properties["AppFriendlyName"].Clear();
  root.Properties["AppIsolated"].Clear();
  root.Properties["AccessFlags"].Clear();
  root.Properties["FrontPageWeb"].Clear();
  root.Properties["AppFriendlyName"].Add(root.Name);
  root.Properties["AppIsolated"].Add(2);
  root.Properties["AccessFlags"].Add(513);
  root.Properties["FrontPageWeb"].Add(1);
  // commit changes
  root.CommitChanges();
  Server.CommitChanges();
  // return the newly created website
  IISWebsite website = new IISWebsite(Server);
  return website;
  }
  目录服务中的节点有自己的名称,但这个名称并不是网站的名字,网站的名字是 Properties["ServerComment"][0]。目录服务的节点的名字是一个整型的数字,我们在创建一个新的节点时,需要查找到当前名字最大的节点,将其名字加1,成为新的节点的名字。在程序中,我使用index变量来获取已经存在的最大名称,然后将其加1,变成我的新的名称。然后调用以下语句添加新的节点。
  DirectoryEntry Server = Services.Children.Add(index.ToString(), IIsWebServer);
  在新的节点添加完成后,我需要对网站的属性进行设置,其中包括:
  网站的名称: ServerComment
  网站的端口: ServerBindings,这里需要注意的是,端口的表示为 :端口: ,即端口两端需要分别有一个冒号。
  到目前为止,我们只是创建了网站,我们还需要为这个网站创建一个主目录:
  // create ROOT for website
  DirectoryEntry root = Server.Children.Add("ROOT", IISWebVirturalDir.IIsVirtualDir);
  root.Properties["path"].Clear();
  root.Properties["path"].Add(rootPath);
  // create application
  if (string.IsNullOrEmpty(appPool))
  {
  root.Invoke("appCreate", 0);
  }
  else
  {
  // use application pool
  root.Invoke("appCreate3", 0, appPool, true);
  }
  root.Properties["AppFriendlyName"].Clear();
  root.Properties["AppIsolated"].Clear();
  root.Properties["AccessFlags"].Clear();
  root.Properties["FrontPageWeb"].Clear();
  root.Properties["AppFriendlyName"].Add(root.Name);
  root.Properties["AppIsolated"].Add(2);
  root.Properties["AccessFlags"].Add(513);
  root.Properties["FrontPageWeb"].Add(1);
  网站必须有一个根目录,这个根目录实际上也是网站的一个子节点,名称为”ROOT”。我创建了类IISWebVirtualDir用以管理虚拟目录,网站的根目录实际上也是一个虚拟目录。我将在后面介绍虚拟目录。
  网站虚拟目录
  网站需要包含虚拟目录,虚拟目录是网站节点的子节点。每一个网站都包含一个根虚拟目录,其节点名称叫做ROOT,这个根虚拟目录即是IIS网站的主路径。 其他的虚拟目录则是这个根虚拟目录的子节点。我使用IISWebVirturalDir来表示虚拟路径。在IISWebsite中,我使用 Root 来表示网站的根虚拟目录:
  ///
  /// Root path
  ///
  public IISWebVirturalDir Root
  {
  get
  {
  foreach (DirectoryEntry entry in websiteEntry.Children)
  {
  if (entry.SchemaClassName == IISWebVirturalDir.IIsVirtualDir)
  {
  return new IISWebVirturalDir(entry);
  }
  }
  throw new WebsiteWithoutRootException(this.Name);
  }
  }
  有了这个根节点,我们就可以使用IISWebVirtualDir.OpenSubVirtualDir来打开任意一个子虚拟目录。
  ///
  /// Open a sub virtual directory
  ///
  /// Name of directory to be opened. Case insensitive.
  /// A IISWebVirtualDir instance if open successfully done.Otherwise null.
  public IISWebVirturalDir OpenSubVirtualDir(string name)
  {
  DirectoryEntry entry = this.FindSubEntry(name);
  if (entry == null)
  {
  return null;
  }
  return new IISWebVirturalDir(entry);
  }
  我们也可以创建一个子虚拟目录,并在创建的过程中设置子虚拟目录的属性:
  ///
  /// Create a sub virtual directory
  ///
  /// Name of the sub virtual directory to be created.
  /// Path of the sub virtual directory.
  ///
  /// Application pool. Application pool with this name would be created if not exist.
  /// Use string.Empty or null to this parameter if you don't want to use a application pool.
  ///
  /// A IISWebVirtualDir if created. Otherwise  null.
  public IISWebVirturalDir CreateSubVirtualDir(string name, string path, string appPool)
  {
  // already exist
  if (this.ExistVirtualDir(name))
  {
  throw new VirtualDirAlreadyExistException(this._entry, path);
  }
  // validate path
  if (System.IO.Directory.Exists(path) == false)
  {
  throw new DirNotFoundException(path);
  }
  DirectoryEntry entry = this._entry.Children.Add(name, IIsVirtualDir);
  entry.Properties["path"].Clear();
  entry.Properties["path"].Add(path);
  // create application
  if (string.IsNullOrEmpty(appPool))
  {
  entry.Invoke("appCreate", 0);
  }
  else
  {
  // use application pool
  entry.Invoke("appCreate3", 0, appPool, true);
  }
  entry.Properties["AppFriendlyName"].Clear();
  entry.Properties["AppIsolated"].Clear();
  entry.Properties["AccessFlags"].Clear();
  entry.Properties["FrontPageWeb"].Clear();
  entry.Properties["AppFriendlyName"].Add(this._entry.Name);
  entry.Properties["AppIsolated"].Add(2);
  entry.Properties["AccessFlags"].Add(513);
  entry.Properties["FrontPageWeb"].Add(1);
  entry.CommitChanges();
  return new IISWebVirturalDir(entry);
  }
  应用程序池
  应用程序池也是用目录服务来操作。只是我们需要打开的根节点,变成了 “IIS://localhost/W3SVC/AppPools/”
  与上面程序一样的原理,我们可以打开,创建应用程序池:
  ///
  /// Open a application pool and return an IISAppPool instance
  ///
  /// application pool name
  /// IISAppPool object
  public static IISAppPool OpenAppPool(string name)
  {
  string connectStr = "IIS://localhost/W3SVC/AppPools/";
  connectStr += name;
  if (IISAppPool.Exsit(name) == false)
  {
  return null;
  }
  DirectoryEntry entry = new DirectoryEntry(connectStr);
  return new IISAppPool(entry);
  }
  ///
  /// create app pool
  ///
  /// the app pool to be created
  /// IISAppPool created if success, else null
  public static IISAppPool CreateAppPool(string name)
  {
  DirectoryEntry Service = new DirectoryEntry("IIS://localhost/W3SVC/AppPools");
  foreach (DirectoryEntry entry in Service.Children)
  {
  if (entry.Name.Trim().ToLower() == name.Trim().ToLower())
  {
  return IISAppPool.OpenAppPool(name.Trim());
  }
  }
  // create new app pool
  DirectoryEntry appPool = Service.Children.Add(name, "IIsApplicationPool");
  appPool.CommitChanges();
  Service.CommitChanges();
  return new IISAppPool(appPool);
  }
  应用程序池上的操作比较简单,我们可以启动或者停止应用程序池:
  ///
  /// Start application pool.
  ///
  public void Start()
  {
  this._entry.Invoke("Start");
  }
  ///
  /// Stop application pool.
  ///
  public void Stop()
  {
  this._entry.Invoke("Stop");
  }
  目录节点的属性
  我们可以根据目录服务节点的SchemaClass访问microsoft.com来获取节点的属性值。但如果我们想枚举属性值的话,也是可以做到的,以下为示例
  代码:
  private void ListProperty(DirectoryEntry server)
  {
  foreach (DirectoryEntry e in server.Children)
  {
  ListProperty(e);
  }
  StringBuilder sb = new StringBuilder();
  sb.AppendLine("Property for " + server.SchemaClassName);
  sb.AppendLine("Name = " + server.Name);
  sb.AppendLine("Path = " + server.Path);
  sb.AppendLine("UserName = " + server.Username);
  sb.AppendLine("====================================================================");
  IEnumerator ie = server.Properties.PropertyNames.GetEnumerator();
  while (ie.MoveNext())
  {
  try
  {
  string name = (string)ie.Current;
  string val = "";
  foreach (object obj in server.Properties[name])
  {
  val += obj.ToString() + ",";
  }
  sb.AppendLine(name + " = " + val.ToString());
  }
  catch (Exception)
  {
  }
  }
  System.IO.StreamWriter sw = new System.IO.StreamWriter("PropertyList_" + server.SchemaClassName + "_" + server.Name + ".txt");
  sw.Write(sb.ToString());
  sw.Close();
  }
  }
  参考文献
  IIS ADSI Provider
  http://msdn.microsoft.com/en-us/library/ms524997(v=VS.90).aspx


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-644614-1-1.html 上篇帖子: IIS主机在某些情况下无法播放视频的设置方法 下篇帖子: IIS7.5 Error Code 0x8007007e HTTP 错误 500.19
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表