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

C# 打造 IIS 管理元件:ASPcn.Management.IISManager 完整原始碼與應用指南

     編輯:關於C語言

前言:程式化管理 IIS 的必要性

手動在 IIS 管理員建立虛擬目錄、設定權限、預設文件、SSL、驗證方式,既繁瑣又易出錯。System.DirectoryServices 命名空間封裝了 ADSI(Active Directory Service Interfaces),允許以 LDAP 風格路徑(IIS://server/W3SVC/1/ROOT)操作 IIS Metabase。本文提供的 IISManager 類別封裝了連線、虛擬目錄 CRUD、批次更新、屬性同步等核心功能,可直接整合至部署腳本、安裝精靈、DevOps 自動化流程。

核心類別架構

  • IISManager:管理連線、虛擬目錄集合、CRUD 操作、批次提交
  • VirtualDirectory:虛擬目錄屬性實體(路徑、權限、驗證、預設文檔等)
  • VirtualDirectories (Hashtable):以虛擬目錄名稱為鍵的集合

完整原始碼(已現代化語法)

using System;
using System.Collections;
using System.DirectoryServices;

namespace ASPcn.Management
{
    public class IISManager
    {
        private string _server = "localhost";
        private string _siteId = "1";
        private VirtualDirectories _virDirs;
        private DirectoryEntry _root;
        private bool _batchMode;

        public string Server { get => _server; set => _server = value; }
        public string WebSite { get => _siteId; set => _siteId = value; }
        public VirtualDirectories VirDirs => _virDirs;

        public IISManager() { }
        public IISManager(string server) { _server = server; }
        public IISManager(string server, string siteId) { _server = server; _siteId = siteId; }

        public void Connect()
        {
            string path = $"IIS://{_server}/W3SVC/{_siteId}/ROOT";
            try
            {
                _root = new DirectoryEntry(path);
                _virDirs = GetVirDirs(_root.Children);
            }
            catch (Exception ex)
            {
                throw new Exception($"無法連線至 IIS 伺服器 [{_server}]", ex);
            }
        }

        public bool Exists(string name) => _virDirs.Contains(name);

        public void Create(VirtualDirectory vdir)
        {
            string path = $"IIS://{_server}/W3SVC/{_siteId}/ROOT/{vdir.Name}";
            if (!_virDirs.Contains(vdir.Name) || _batchMode)
            {
                try
                {
                    var newDir = _root.Children.Add(vdir.Name, "IIsWebVirtualDir");
                    newDir.Invoke("AppCreate", true);
                    newDir.CommitChanges();
                    _root.CommitChanges();
                    UpdateDirInfo(newDir, vdir);
                }
                catch (Exception ex) { throw new Exception("建立虛擬目錄失敗", ex); }
            }
            else throw new Exception("虛擬目錄已存在");
        }

        public VirtualDirectory GetVirDir(string name)
        {
            if (!_virDirs.Contains(name)) throw new Exception("虛擬目錄不存在");
            var vdir = _virDirs.Find(name);
            vdir.Flag = 2; // 標記為更新狀態
            return vdir;
        }

        public void Update(VirtualDirectory vdir)
        {
            if (!_virDirs.Contains(vdir.Name)) throw new Exception("虛擬目錄不存在");
            var de = _root.Children.Find(vdir.Name, "IIsWebVirtualDir");
            UpdateDirInfo(de, vdir);
        }

        public void Delete(string name)
        {
            if (!_virDirs.Contains(name)) throw new Exception("虛擬目錄不存在");
            _root.Invoke("Delete", new object[] { "IIsWebVirtualDir", name });
            _root.CommitChanges();
        }

        public void UpdateBatch() => BatchUpdate(_virDirs);
        public void UpdateBatch(VirtualDirectories vdirs) => BatchUpdate(vdirs);

        private void BatchUpdate(VirtualDirectories vdirs)
        {
            _batchMode = true;
            foreach (VirtualDirectory vd in vdirs.Values)
            {
                switch (vd.Flag)
                {
                    case 1: Create(vd); break;
                    case 2: Update(vd); break;
                }
            }
            _batchMode = false;
        }

        private void UpdateDirInfo(DirectoryEntry de, VirtualDirectory vd)
        {
            de.Properties["AccessRead"][0] = vd.AccessRead;
            de.Properties["AccessWrite"][0] = vd.AccessWrite;
            de.Properties["AccessExecute"][0] = vd.AccessExecute;
            de.Properties["AccessScript"][0] = vd.AccessScript;
            de.Properties["AccessSSL"][0] = vd.AccessSSL;
            de.Properties["AuthAnonymous"][0] = true; // 隱含
            de.Properties["AnonymousUserName"][0] = vd.AnonymousUserName;
            de.Properties["AnonymousUserPass"][0] = vd.AnonymousUserPass;
            de.Properties["AuthBasic"][0] = vd.AuthBasic;
            de.Properties["AuthNTLM"][0] = vd.AuthNTLM;
            de.Properties["ContentIndexed"][0] = vd.ContentIndexed;
            de.Properties["EnableDefaultDoc"][0] = vd.EnableDefaultDoc;
            de.Properties["EnableDirBrowsing"][0] = vd.EnableDirBrowsing;
            de.Properties["DefaultDoc"][0] = vd.DefaultDoc;
            de.Properties["Path"][0] = vd.Path;
            de.CommitChanges();
        }

        private VirtualDirectories GetVirDirs(DirectoryEntries entries)
        {
            var dict = new VirtualDirectories();
            foreach (DirectoryEntry de in entries)
            {
                if (de.SchemaClassName == "IIsWebVirtualDir")
                {
                    var vd = new VirtualDirectory(de.Name)
                    {
                        AccessRead = (bool)de.Properties["AccessRead"][0],
                        AccessWrite = (bool)de.Properties["AccessWrite"][0],
                        AccessExecute = (bool)de.Properties["AccessExecute"][0],
                        AccessScript = (bool)de.Properties["AccessScript"][0],
                        AccessSSL = (bool)de.Properties["AccessSSL"][0],
                        AuthBasic = (bool)de.Properties["AuthBasic"][0],
                        AuthNTLM = (bool)de.Properties["AuthNTLM"][0],
                        ContentIndexed = (bool)de.Properties["ContentIndexed"][0],
                        EnableDefaultDoc = (bool)de.Properties["EnableDefaultDoc"][0],
                        EnableDirBrowsing = (bool)de.Properties["EnableDirBrowsing"][0],
                        DefaultDoc = (string)de.Properties["DefaultDoc"][0],
                        Path = (string)de.Properties["Path"][0],
                        AnonymousUserName = (string)de.Properties["AnonymousUserName"][0],
                        AnonymousUserPass = (string)de.Properties["AnonymousUserPass"][0],
                        Flag = 0
                    };
                    dict.Add(vd.Name, vd);
                }
            }
            return dict;
        }
    }

    public class VirtualDirectory
    {
        public int Flag { get; set; }
        public string Name { get; set; }
        public string Path { get; set; } = @"C:\";
        public string DefaultDoc { get; set; } = "default.htm,default.aspx,default.asp,index.htm";
        public bool AccessRead { get; set; } = true;
        public bool AccessWrite { get; set; }
        public bool AccessExecute { get; set; }
        public bool AccessScript { get; set; }
        public bool AccessSSL { get; set; }
        public bool AuthBasic { get; set; }
        public bool AuthNTLM { get; set; } = true;
        public bool ContentIndexed { get; set; }
        public bool EnableDefaultDoc { get; set; } = true;
        public bool EnableDirBrowsing { get; set; }
        public string AnonymousUserName { get; set; } = "";
        public string AnonymousUserPass { get; set; } = "";

        public VirtualDirectory() { }
        public VirtualDirectory(string name) { Name = name; }
    }

    public class VirtualDirectories : Hashtable
    {
        public VirtualDirectory Find(string name) => this[name] as VirtualDirectory;
    }
}

使用範例:自動化部署虛擬目錄

var iis = new IISManager("192.168.1.100", "1"); // 遠端伺服器,站點 ID 1
iis.Connect();

// 建立新虛擬目錄
var vdir = new VirtualDirectory
{
    Name = "MyApp",
    Path = @"D:\WebApps\MyApp",
    AccessRead = true,
    AccessScript = true,
    AccessWrite = false,
    AuthNTLM = true,
    AuthBasic = false,
    EnableDefaultDoc = true,
    DefaultDoc = "index.aspx,default.aspx",
    AnonymousUserName = "IUSR_WEB",
    AnonymousUserPass = "P@ssw0rd"
};
iis.Create(vdir);

// 批次更新多個虛擬目錄
iis.VirDirs["OldApp"].AccessWrite = true;
iis.VirDirs["OldApp"].Flag = 2; // 標記更新
iis.UpdateBatch();

Console.WriteLine("部署完成");

關鍵技術細節

1. IIS Metabase 路徑結構

IIS://server/W3SVC/siteId/ROOT/vdirName
// 範例:IIS://localhost/W3SVC/1/ROOT/MyApp
  • W3SVC:Web 服務
  • siteId:網站識別碼(預設網站通常為 "1")
  • ROOT:網站根節點
  • IIsWebVirtualDir:虛擬目錄 Schema 類別名

2. 應用程式建立

newDir.Invoke("AppCreate", true) 將虛擬目錄標記為 IIS 應用程式(獨立應用程式域、獨立 web.config、可設定應用程式池)。對應操作:AppDelete、AppUnload。

3. 常用屬性對照表

VirtualDirectory 屬性Metabase 屬性說明
AccessReadAccessRead讀取靜態檔案
AccessWriteAccessWrite寫入/上傳
AccessScriptAccessScript執行腳本
AccessExecuteAccessExecute執行可執行檔
AccessSSLAccessSSL要求 SSL
AuthBasicAuthBasic基本驗證
AuthNTLMAuthNTLM整合 Windows 驗證
EnableDirBrowsingEnableDirBrowsing目錄瀏覽
DefaultDocDefaultDoc預設文檔清單
PathPath實體路徑

4. 批次模式設計

Flag 欄位標記狀態:0=無變更、1=新建、2=更新。UpdateBatch 統一提交,減少 Metabase 寫入次數,提升效能。

遷移至 Microsoft.Web.Administration (IIS 7+)

IIS 7 引入新設定系統,建議使用 Microsoft.Web.Administration (nuget: Microsoft.Web.Administration):

using Microsoft.Web.Administration;

var server = new ServerManager();
var site = server.Sites["Default Web Site"];
var app = site.Applications.Add("/MyApp", @"D:\WebApps\MyApp");
app.VirtualDirectories[0].PhysicalPath = @"D:\WebApps\MyApp";
app.VirtualDirectories[0].LogonMethod = LogonMethod.ClearText;
app.VirtualDirectories[0].UserName = "IUSR_WEB";
app.VirtualDirectories[0].Password = "P@ssw0rd";
server.CommitChanges();

新 API 強型別、支援應用程式池管理、模組管線模式、集中式 XML 設定,為現代 IIS 自動化首選。

總結

IISManager 以 System.DirectoryServices 封裝 IIS 6 Metabase 操作,提供物件導向、批次提交、屬性同步的完整介面。理解其原理後,可輕鬆遷移至 IIS 7+ 的 Microsoft.Web.Administration,實現從傳統部署腳本到現代 IaC(基礎設施即代碼)的演進。

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