
Великий МунаБудвин
   
Профиль
Группа: Экс. модератор
Сообщений: 2646
Регистрация: 15.7.2004
Где: город-герой Минск
Репутация: 21 Всего: 61
|
Думаю, у многих из вас, друзья-программеры, возникала необходимость поработать с метаданными 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 } }
|
|