首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

C# 操作 IIS 完全指南:建立、刪除、查詢網站(DirectoryServices 實戰)

     編輯:關於C語言

前言:為什麼要用代碼管理 IIS?

自動化部署、CI/CD 流水線、多租戶 SaaS 平台、動態建立客戶專屬站點——這些場景都需要以程式碼控制 IIS。.NET 透過 System.DirectoryServices 操作 IIS Metabase(IIS 6)或 Configuration System(IIS 7+),本文提供建立、刪除、查詢網站的完整實作代碼。

核心類別與命名空間

  • DirectoryEntry:代表 IIS 設定樹中的節點(網站、虛擬目錄、應用程式池等)。
  • DirectoryEntries:子節點集合,用於新增/移除節點。
  • PropertyValueCollection:節點屬性值集合(如 ServerBindings、ServerComment、Path)。
  • 需引用 System.DirectoryServices.dll,專案需以 **Administrator 權限** 執行。

關鍵路徑與 Schema

路徑說明
IIS://localhost/W3SVC網站容器根節點
IIS://localhost/W3SVC/{SiteId}特定網站節點
IIS://localhost/W3SVC/{SiteId}/ROOT網站根虛擬目錄

關鍵 Schema 類別:IISWebServer(網站)、IISWebVirtualDir(虛擬目錄)。

實用工具方法

1. 取得可用的新網站 ID(最小未使用正整數)

public string GetNewWebSiteId() {
    var ids = new List();
    using (var root = new DirectoryEntry("IIS://localhost/W3SVC")) {
        foreach (DirectoryEntry child in root.Children) {
            if (child.SchemaClassName == "IISWebServer" && int.TryParse(child.Name, out int id))
                ids.Add(id);
        }
    }
    ids.Sort();
    int next = 1;
    foreach (int id in ids) {
        if (id == next) next++;
        else break;
    }
    return next.ToString();
}

2. 依網站名稱(Comment 或 Host Header)查詢 Site ID

public string GetWebSiteIdByName(string siteName) {
    using (var root = new DirectoryEntry("IIS://localhost/W3SVC")) {
        foreach (DirectoryEntry site in root.Children) {
            if (site.SchemaClassName != "IISWebServer") continue;
            
            // 比對 ServerComment(網站描述)
            if (site.Properties["ServerComment"]?.Value?.ToString() == siteName)
                return site.Name;
            
            // 比對 ServerBindings(IP:Port:HostHeader)
            if (site.Properties["ServerBindings"]?.Value is string bindings && bindings.Contains(siteName))
                return site.Name;
        }
    }
    return string.Empty;
}

建立網站完整流程

public void CreateWebSite(string siteName, string ip, string port, string hostHeader, string physicalPath) {
    string siteId = GetNewWebSiteId();
    string bindString = $"{ip}:{port}:{hostHeader}";

    using (var root = new DirectoryEntry("IIS://localhost/W3SVC")) {
        // 1. 建立 IISWebServer 節點
        using (var site = root.Children.Add(siteId, "IISWebServer")) {
            site.Properties["ServerBindings"].Value = bindString;
            site.Properties["ServerComment"].Value = siteName;
            site.CommitChanges(); // 必須先 Commit 才能建立子節點

            // 2. 建立根虛擬目錄
            using (var vdir = site.Children.Add("ROOT", "IISWebVirtualDir")) {
                vdir.Properties["Path"].Value = physicalPath;
                vdir.CommitChanges();
            }
        }
    }
    Console.WriteLine($"網站 [{siteName}] 建立完成,ID={siteId}, 綁定={bindString}, 路徑={physicalPath}");
}

刪除網站

public void DeleteWebSite(string siteName) {
    string siteId = GetWebSiteIdByName(siteName);
    if (string.IsNullOrEmpty(siteId)) {
        Console.WriteLine($"找不到網站:{siteName}");
        return;
    }

    using (var root = new DirectoryEntry("IIS://localhost/W3SVC"))
    using (var site = new DirectoryEntry($"IIS://localhost/W3SVC/{siteId}")) {
        root.Children.Remove(site);
        root.CommitChanges();
    }
    Console.WriteLine($"網站 [{siteName}] (ID={siteId}) 已刪除");
}

查詢並列出所有網站詳細資訊

public List ListAllWebSites() {
    var list = new List();
    using (var root = new DirectoryEntry("IIS://localhost/W3SVC")) {
        foreach (DirectoryEntry site in root.Children) {
            if (site.SchemaClassName != "IISWebServer") continue;

            string id = site.Name;
            string comment = site.Properties["ServerComment"]?.Value?.ToString() ?? "";
            string bindings = site.Properties["ServerBindings"]?.Value?.ToString() ?? "";
            
            // 解析 IP:Port:HostHeader
            string ip = "", port = "", host = "";
            if (!string.IsNullOrEmpty(bindings)) {
                var parts = bindings.Split(':');
                if (parts.Length >= 3) { ip = parts[0]; port = parts[1]; host = parts[2]; }
            }

            // 取得物理路徑
            string physPath = "";
            foreach (DirectoryEntry vdir in site.Children) {
                if (vdir.SchemaClassName == "IISWebVirtualDir" && vdir.Name == "ROOT") {
                    physPath = vdir.Properties["Path"]?.Value?.ToString() ?? "";
                    break;
                }
            }

            list.Add(new WebSiteInfo {
                Id = id, Name = comment, Ip = ip, Port = port, HostHeader = host, PhysicalPath = physPath
            });
        }
    }
    return list;
}

public class WebSiteInfo {
    public string Id { get; set; }
    public string Name { get; set; }
    public string Ip { get; set; }
    public string Port { get; set; }
    public string HostHeader { get; set; }
    public string PhysicalPath { get; set; }
}

進階主題與避坑指南

  1. IIS 7+ 應用程式池管理:建立網站後常需建立/指派專屬 AppPool,操作路徑 IIS://localhost/W3SVC/AppPools,Schema 為 IIsApplicationPool。
  2. 權限問題:代碼必須在 **管理員權限** 下執行,否則 CommitChanges 會拋出 UnauthorizedAccessException。
  3. Microsoft.Web.Administration (IIS 7+ 推薦):新專案建議改用 ServerManager 類別(需引用 Microsoft.Web.Administration.dll),API 更現代、強型別、支援 applicationHost.config 直接操作。
  4. 綁定衝突檢查:建立前應掃描現有 ServerBindings,避免 IP:Port:HostHeader 重複導致網站無法啟動。
  5. 實體路徑權限:確保 IIS_IUSRS / ApplicationPoolIdentity 對物理路徑有讀取/執行權限。

總結

掌握 DirectoryEntry 操作 IIS Metabase 的核心模式——**連線根節點 → 遍歷/新增/移除子節點 → 設定屬性 → CommitChanges**——即可實現網站全生命週期自動化管理。配合 ServerManager 現代 API,構建穩健的自動化部署與多租戶平台基礎設施。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved