Полезное для программистов:

Фриланс
Новости
Статьи
   
Рубрики:


Работаем с IIS из .NET приложения

Поиск:
Думаю, у многих из вас, друзья-программеры, возникала необходимость поработать с метаданными IIS'а из своего приложения - вирутальную директорию создать или удалить, отобразить список веб-сайтов, и т.д. Предлагаю вашему вниманию несколько классов для выполнения этих операций.

DICLAIMER: нижепреведенный код идет под лицензией GNU Lesser General Public License (LGPL). Это значит, что вы можете делать с этим кодом все, что захотите, но если будете вносить изменения - поделитесь ими с автором. Полный текст лицензии можно прочитать тут: http://www.gnu.org/copyleft/lgpl.html

Код

/*
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
using System;
using System.Management;
using System.Management.Instrumentation;
using System.DirectoryServices;
using System.IO;
using System.Collections;
using System.Collections.Specialized;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace Vingrad.IISTools
{
    #region классы WebSiteInfo: веб-сайты
    public class WebSiteInfo
    {
  private string _wsName = string.Empty;
  /// <summary>
  /// Имя веб-сайта (Default Web Site например)
  /// </summary>
  public string Name
  {
    get { return _wsName; }
  }

  private int _wsNum = 0;
  /// <summary>
  /// Номер веб-сайта
  /// </summary>
  public int Number
  {
    get { return _wsNum; }
  }

  private string _url = string.Empty;
  /// <summary>
  /// URL для доступа к сайту
  /// </summary>
  public string URL
  {
    get { return _url; }
  }

  public DirectoryEntry DirectoryEntry = null;
    
  private string extractURL(string extractFrom)
  {
    // первый вид URL полученного из DirectoryEntry.Properties["ServerBindings"]
    // :номер порта:. это означает, что веб-сайт доступен на всех IP адресах машины
    if(extractFrom.IndexOf(".") <= 0)
    {
    string[] tokens = extractFrom.Split(':');

    // поскольку IP не указан, то возвращаем 127.0.0.1
    if(tokens[1] != "80")
    {
     return "localhost" + ":" + tokens[1];
    }
    else
    {
     return "localhost";
    }
    }
    // второй вид URL - x.x.x.x:номер порта:
    // в таком случае в DirectoryEntry.Properties["ServerBindings"] может быть несколько
    // значений. Это сигнализирует о том, что сайт доступен на одном или нескольких IP 
    // адресах. нас интересует только первый :)
    else if(extractFrom.Length > 8)
    {
    // возвращаем строку без последнего ":"
    // если в конце стоит :80, то тоже отбрасываем
    string t = extractFrom.Substring(0, extractFrom.LastIndexOf(':'));
    
    if(t.EndsWith(":80"))
     return t.Substring(0, t.Length - 3);
    else
     return t;
    }
    else
    return string.Empty;
  }

  /// <summary>
  /// Конструирует объект
  /// </summary>
  public WebSiteInfo(DirectoryEntry createFrom)
  {
    // получаем нужные нам свойства
    string siteName = (string)createFrom.Properties["ServerComment"].Value;
    int number = int.Parse(createFrom.Name);

    _wsName = siteName;
    _wsNum = number;

    string urlVal = string.Empty;
    if(createFrom.Properties["ServerBindings"].Value.GetType().IsArray)
    urlVal = (string)((object[])createFrom.Properties["ServerBindings"].Value)[0];
    else
    urlVal = (string)createFrom.Properties["ServerBindings"].Value;

    _url = extractURL(urlVal);

    DirectoryEntry = createFrom;
  }

  public override string ToString()
  {
    return Name;
  }
    }

    public class WebSiteInfoCollection : Hashtable
    {
  public void Add(WebSiteInfo siteInfo)
  {
    base.Add(siteInfo.Number, siteInfo);
  }
    }

    #endregion

    #region классы VirtualDirectoryInfo: рекурсивный список виртуальных директорий
    public class VirtualDirectoryInfo
    {
  string _name = string.Empty;
  /// <summary>
  /// Имя директории.
  /// </summary>
  /// <remarks>
  /// ROOT - имя корневой директории
  /// </remarks>
  public string Name
  {
    get 
    { 
    if(Parent == null)
     return @"/";
    else
     return _name; 
    }
  }

  VirtualDirectoryInfo _parent = null;
  /// <summary>
  /// Ссылка на родителя. У ROOT родителя нет - null
  /// </summary>
  public VirtualDirectoryInfo Parent
  {
    get { return _parent; }
  }

  VirtualDirectoryInfoCollection _children = new VirtualDirectoryInfoCollection();
  /// <summary>
  /// Список под-директорий
  /// </summary>
  public VirtualDirectoryInfoCollection Children
  {
    get { return _children; }
  }

  /// <summary>
  /// Возвращает полное имя виртуальной директории в виде "/Folder1/Subfolder1"
  /// </summary>
  public string FullName
  {
    get
    {
    if(Parent != null)
     return Parent.FullName + Name + "/";
    else
     return "/";
    }
  }

  /// <summary>
  /// Возвращает ссылку на DirectoryEntry для данного объекта
  /// </summary>
  public DirectoryEntry DirectoryEntry = null;

  private string _path = string.Empty;
  /// <summary>
  /// Возвращает путь, на который указывает данная виртуальная директория
  /// </summary>
  public string Path
  {
    get { return _path; }
  }

  public bool IsApplication
  {
    get
    {
    try
    {
     return ((string)DirectoryEntry.Properties["AppRoot"].Value).ToLower() != IISHelper.NAME_DEFAULT_APP_ROOT.ToLower();
    }
    catch(Exception ex)
    {
     Trace.WriteLine(ex.ToString(), "IsApplication");
     return false;
    }
    }
  }

  private WebSiteInfo _ws = null;
  /// <summary>
  /// Возвращает ссылку на веб-сайт
  /// </summary>
  public WebSiteInfo WebSite
  {
    get { return _ws; }
  }

  public VirtualDirectoryInfo()
  {
  }

  public VirtualDirectoryInfo(DirectoryEntry createFrom, VirtualDirectoryInfo parentDir, WebSiteInfo site)
  {
    _parent = parentDir;
    _name = createFrom.Name;
    DirectoryEntry = createFrom;
    _ws = site;

    if(((string)createFrom.Properties["KeyType"].Value) == IISHelper.SCHEMA_VIRTUAL_DIR)
    _path = (string)createFrom.Properties["Path"].Value;
  }

  public override string ToString()
  {
    return Name;
  }
    }

    public class VirtualDirectoryInfoCollection : ArrayList
    {
  public override void Sort(IComparer comparer)
  {
    base.Sort(comparer);

    foreach (VirtualDirectoryInfo vdir in this)
    {
    if(vdir.Children.Count > 0)
     vdir.Children.Sort(comparer);
    }
  }
    }
    #endregion

    /// <summary>
    /// Класс для взаимодействия с IIS
    /// </summary>
    public class IISHelper
    {
  internal class VirtualDirectoryInfoComparer : IComparer
  {
    #region IComparer Members

    public int Compare(object x, object y)
    {
    VirtualDirectoryInfo vx = (VirtualDirectoryInfo)x;
    VirtualDirectoryInfo vy = (VirtualDirectoryInfo)y;

    return vx.Name.CompareTo(vy.Name);
    }

    #endregion
  }

  internal const string IIS_PATH = "IIS://localhost/W3SVC";
  internal const string 
    SCHEMA_WEBSERVER = "IIsWebServer",
    SCHEMA_VIRTUAL_DIR = "IIsWebVirtualDir",
    SCHEMA_WEB_DIR = "IIsWebDirectory",
    NAME_ROOT_DIR = "ROOT",
    NAME_DEFAULT_IP = "127.0.0.1",
    NAME_DEFAULT_APP_ROOT = "/LM/W3SVC/1/ROOT";

  private static Exception _lastEx = null;
  public static Exception LastException
  {
    get { return _lastEx; }
  }

  #region получение списка веб-сайтов
  public static WebSiteInfoCollection GetWebSiteList()
  {
    WebSiteInfoCollection result = new WebSiteInfoCollection();

    // перебираем все записи в корневом узле схемы IIS'а
    DirectoryEntry root = new DirectoryEntry(IIS_PATH);
    IEnumerator en = root.Children.GetEnumerator();

    while(en.MoveNext())
    {
    DirectoryEntry current = (DirectoryEntry) en.Current;

    // данный класс схемы означает, что найден веб-сайт
    if(current.SchemaClassName == SCHEMA_WEBSERVER)
    {
     result.Add(new WebSiteInfo(current));
    }
    }

    return result;
  }

  #endregion

  #region получение рекурсивного списка вирт.директорий
  public static VirtualDirectoryInfo GetVDir(int webSiteNum, string vdirName)
  {
    VirtualDirectoryInfo vdir = new VirtualDirectoryInfo();

    // перебираем все записи в корневом узле схемы IIS'а
    WebSiteInfo webSite = (WebSiteInfo)GetWebSiteList()[webSiteNum];
    IEnumerator en = webSite.DirectoryEntry.Children.GetEnumerator();

    while(en.MoveNext())
    {
    DirectoryEntry current = (DirectoryEntry)en.Current;
    if(current.SchemaClassName == SCHEMA_VIRTUAL_DIR || current.SchemaClassName == SCHEMA_WEB_DIR)
    {
     if(current.Name == vdirName)
      return new VirtualDirectoryInfo(current, null, webSite);
     else
     {
      vdir = processToFindVDir(current, vdirName, webSite);
      if(vdir != null)
       return vdir;
     }
    }
    }

    return null;
  }

  private static VirtualDirectoryInfo processToFindVDir(DirectoryEntry parent, string vdirName, WebSiteInfo site)
  {
    IEnumerator en = parent.Children.GetEnumerator();

    while(en.MoveNext())
    {
    DirectoryEntry current = (DirectoryEntry)en.Current;
    // данная проверка нужна, чтобы выбрать только каталоги, а не сами файлы
    if(current.SchemaClassName == SCHEMA_VIRTUAL_DIR || current.SchemaClassName == SCHEMA_WEB_DIR)
    {
     PropertyValueCollection val = current.Properties["KeyType"];

     if(val != null && ((string)val.Value == SCHEMA_WEB_DIR ||
      current.SchemaClassName == SCHEMA_VIRTUAL_DIR))
     {
      if(current.Name == vdirName)
       return new VirtualDirectoryInfo(current, null, site);
     }
    }

    VirtualDirectoryInfo ret = processToFindVDir(current, vdirName, site);
    if(ret != null)
     return ret;
    }

    return null;
  }



  public static VirtualDirectoryInfo GetRootVDir(WebSiteInfo webSite)
  {
    VirtualDirectoryInfo root = new VirtualDirectoryInfo();

    // перебираем все записи в корневом узле схемы IIS'а
    IEnumerator en = webSite.DirectoryEntry.Children.GetEnumerator();

    while(en.MoveNext())
    {
    DirectoryEntry current = (DirectoryEntry)en.Current;

    if(current.SchemaClassName == SCHEMA_VIRTUAL_DIR || current.SchemaClassName == SCHEMA_WEB_DIR)
    {     
     if(current.Name.ToUpper() == NAME_ROOT_DIR)
      root = new VirtualDirectoryInfo(current, null, webSite);

     root.Children.AddRange(processVDirChildren(current, root, webSite));
     root.Children.Sort(new VirtualDirectoryInfoComparer());
    }
    }

    return root;
  }

  private static VirtualDirectoryInfoCollection processVDirChildren(DirectoryEntry parent, VirtualDirectoryInfo parentVDir, WebSiteInfo site)
  {
    IEnumerator en = parent.Children.GetEnumerator();
    VirtualDirectoryInfoCollection result = new VirtualDirectoryInfoCollection();

    while(en.MoveNext())
    {
    DirectoryEntry current = (DirectoryEntry)en.Current;
    // данная проверка нужна, чтобы выбрать только каталоги, а не сами файлы
    if(current.SchemaClassName == SCHEMA_VIRTUAL_DIR || current.SchemaClassName == SCHEMA_WEB_DIR)
    {
     PropertyValueCollection val = current.Properties["KeyType"];

     if(val != null && ((string)val.Value == SCHEMA_WEB_DIR ||
      current.SchemaClassName == SCHEMA_VIRTUAL_DIR))
     {
      VirtualDirectoryInfo vdir = new VirtualDirectoryInfo(current, parentVDir, site);
      vdir.Children.AddRange(processVDirChildren(current, vdir, site));
      result.Add(vdir);
     }
    }
    }

    return result;
  }

  #endregion

  #region создание новой/удаление старой виртуальной директории
  /// <summary>
  /// Создает новую виртуальную директорию 
  /// </summary>
  /// <param name="name">имя</param>
  /// <param name="path">путь, куда уазывать</param>
  /// <param name="createApp">создавать ли Application для директории</param>
  /// <param name="parent">ссылка на родительскую директорию</param>
  /// <returns></returns>
  public static VirtualDirectoryInfo CreateVDir(string name, string path, bool createApp, VirtualDirectoryInfo parent)
  {
    try
    {
    VirtualDirectoryInfo vdir = null;
    DirectoryEntry vdirEntry = null;

    try
    {
     vdirEntry = parent.DirectoryEntry.Children.Add(name, SCHEMA_VIRTUAL_DIR);
     vdirEntry.CommitChanges();
    } // может быть исключение, если файлы лежат в wwwroot, и там же
     // создается вирт.директория
    catch(Exception eex)
    {
     Trace.WriteLine(eex.ToString(), "CreateVDir");

     try
     {
      if(parent == null)
       MessageBox.Show("parent=null");
      else if(parent.DirectoryEntry == null)
       MessageBox.Show("parent.de=null");
      else if(parent.DirectoryEntry.Children == null)
       MessageBox.Show("parent.de.children=null");

      IEnumerator parentFinder = (IEnumerator)parent.DirectoryEntry.Children.GetEnumerator();
      
      while(parentFinder.MoveNext())
      {
       DirectoryEntry cur = (DirectoryEntry)parentFinder.Current;

       if((cur.SchemaClassName == SCHEMA_WEB_DIR && cur.Name == name))
       {
        vdirEntry = cur;
        break;
       }
       else if(cur.SchemaClassName == SCHEMA_VIRTUAL_DIR && cur.Name == name)
       {
        vdirEntry = cur;
        createApp = false;
        break;
       }
      }

      if(vdirEntry == null)
      {
       _lastEx = new Exception("vdirEntry = null");
       return null;
      }
      
            /*vdirEntry = parent.DirectoryEntry.Children.Find(name);
      
      if(vdirEntry == null)
      {
       vdirEntry = parent.DirectoryEntry.Children.Find(name, SCHEMA_WEB_DIR);
      
       if(vdirEntry == null)
       {
        vdirEntry = parent.DirectoryEntry.Children.Find(name, SCHEMA_VIRTUAL_DIR);
        if(vdirEntry == null)
        {
         _lastEx = new Exception("vdirEntry = null");
         return null;
        }
       }
      }*/
     }
     catch(Exception ex)
     {
      Trace.WriteLine(ex.ToString(), "CreateVDir");
      _lastEx = ex;
      return null;
     }
    }

    vdirEntry.Properties["Path"].Value = path;
    vdirEntry.CommitChanges();

    if(createApp)
    {
     vdirEntry.Invoke("AppCreate2", 2);
     vdirEntry.Invoke("Put", "AppFriendlyName", "EP32");
    }

    vdirEntry.CommitChanges();

    vdir = new VirtualDirectoryInfo(vdirEntry, parent, parent.WebSite);

    if(parent != null)
     parent.Children.Add(vdir);

    return vdir;
    }
    catch(Exception ex)
    {
    Trace.WriteLine(ex.ToString(), "CreateVDir");
    _lastEx = ex;
    return null;
    }
  }

  public static void RemoveVDir(VirtualDirectoryInfo vdir)
  {
    vdir.DirectoryEntry.DeleteTree();
  }
  #endregion

  #region отладочные функции для получения дерева метаданных из IIS
  public static TreeNode debugGetFullSchemaTreeNode()
  {
    StringCollection result = new StringCollection();
    TreeNode ndparent = new TreeNode("IIS");

    DirectoryEntry myDE = new DirectoryEntry(IIS_PATH);
    DirectoryEntries myEntries = myDE.Children;
    IEnumerator en = myEntries.GetEnumerator();

    while(en.MoveNext())
    {
    DirectoryEntry current = (DirectoryEntry) en.Current;
    TreeNode nd = new TreeNode(string.Format("Schema {0}, Name {1}", current.SchemaClassName, current.Name));
    
    processProperties(current, ref nd);
    recursiveProcessChildren(current, ref nd);
    ndparent.Nodes.Add(nd);
    }

    ndparent.ExpandAll();

    return ndparent;
  }

  private static void processProperties(DirectoryEntry entry, ref TreeNode node)
  {
    try
    {
    PropertyCollection props = entry.Properties;
    IEnumerator en = props.PropertyNames.GetEnumerator();
    TreeNode propNode = new TreeNode("Properties");
    
    while(en.MoveNext())
    {
     string propName = (string)en.Current;
    
     PropertyValueCollection values = props[(string)propName];
     TreeNode valNode = new TreeNode((string)propName);

     foreach(object val in values)
     {
      valNode.Nodes.Add(string.Format("value={0}", val));
      //if(((string)val) == "Default Web Site")
      //    Debugger.Break();
     }

     propNode.Nodes.Add(valNode);
    }

    node.Nodes.Add(propNode);
    }
    catch{}

    //}
    //catch(COMException ex)
    //{
    //    propNode.Nodes.Add(ex.ToString());
    //}
  }

  private static void recursiveProcessChildren(DirectoryEntry entry, ref TreeNode parent)
  {
    DirectoryEntries children = entry.Children;
    IEnumerator en = children.GetEnumerator();

    while(en.MoveNext())
    {
    DirectoryEntry current = (DirectoryEntry) en.Current;
    TreeNode nd = new TreeNode(string.Format("Schema {0}, Name {1}", current.SchemaClassName, current.Name));
    processProperties(current, ref nd);
    recursiveProcessChildren(current, ref nd);
    nd.ExpandAll();
    parent.Nodes.Add(nd);
    }
  }

  #endregion
    }
}
Автор: arilou






Просмотров: 4860

 

 

Новые статьи:


Популярные:
  1. Как сделать цикличным проигрывание MIDI-файла?
  2. Создание AVI файла из рисунков
  3. Как устройство "отключить в данной конфигурации"?
  4. Kто в данный момент присоединен через Сеть?
  5. Как узнать количество доступной памяти?
  6. Как реализовать в RichEdit разноцветный текст?
  7. Как скрыть свое приложение от ProcessViewer
  8. Как программно нажать/скрыть/показ кнопку "Start"?
  9. Модуль работы с ресурсами в PE файлах
10. Функции вызова диалоговых окон выбора
11. Проверка граматики средствами Word'а из Delphi.
12. Модуль для упрощенного вызова сообщений
13. Функции для записи и чтение своих данных в, ЕХЕ- файле
14. Рекурсивный просмотр директорий
15. Network Traffic Monitor
16. Разные модули
17. Универсальная функция для обращения к любым экспортируем функциям DLL
18. Библиотека от VladS
19. Протектор для UPX'а
20. Еще об ICQ, сообщения по контакт листу?
21. Использование открытых интерфейсов
22. Теория и практика использования RTTI
23. Работа с TApplication
24. Примеры использования Drag and Drop для различных визуальных компонентов
25. Что такое порт? Правила для работы с портами
26. Симфония на клавиатуре
27. Загрузка DLL
28. Исправление автоинкремента
29. Взаимодействие с чужими окнами
30. Проверить дубляжи в столбце


 

 

 
 
На главную