IIS 6 網站要移轉到 Windows 2012 R2 主機,轉換前打算匯出網站完整設定檢視一次,排除過期或廢棄的網站應用程式,另外還想嘗試依據現有設定產生設定網站應用程式與虛擬目錄的自動化 Script,第一步要取得現有網站設定資料。

使用 PowerShell Get-WmiObject -class IISWebVirtualDirSetting -namespace "root/MicrosoftIISv2" -computername "IIS6主機名稱" -authentication 6(參考:Get-WmiObject 參數說明)可列出虛擬目錄及網站應用程式相關設定,要寫程式對匯出資料進行花式應用,轉成 JSON 是首選,而 PowerShell 有個 ConvertTo-Json Cmdlet 可以幫忙。

看似完美對吧?But!天殺的 But 又出現惹~當屬性為物件陣列(如下圖的 HttpCustomHeaders 及 HttpErrors)時,ConvertTo-Json 會轉成"System.Management.ManagementBaseObject"組成的字串陣列,看不出其中內容。

ConvertTo-Json 有個 –Depth 參數指定序列化深度,實測提高到 5 才能看到 HttpErrors 內容:

不過 Depth 提高後,資料結構裡供系統用的 Properties、SystemProperties、Qualifiers、ClassPath 也會被展開,資料變得雜亂仰賴後續過濾簡化。心想橫豎都要寫程式,不如擷取邏輯也自己寫吧!

使用 System.Management.ManagementObjectSearcher 可取回與 Get-WmiObjet 相同的查詢結果,配合 Json.NET LINQ 好用的 JObject、JArray、JValue 動態組裝產生 JSON:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Management;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
 
class IISSettingDumper
{
    public static void Dump()
    {
        ConnectionOptions options = new ConnectionOptions();
        options.Impersonation = System.Management.ImpersonationLevel.Impersonate;
        options.Authentication = AuthenticationLevel.PacketPrivacy;
        ManagementScope scope = new ManagementScope(@"\\.\root\MicrosoftIISv2", options);
        scope.Connect();
        ObjectQuery query = new ObjectQuery("SELECT * FROM IISWebVirtualDirSetting");
        ManagementObjectSearcher searcher = new ManagementObjectSearcher(scope, query);
        ManagementObjectCollection res = searcher.Get();
        JArray pool = new JArray();
        foreach (var m in res)
        {
            JObject jo = new JObject();
            foreach (var p in m.Properties)
            {
 
                if (p.Value is ManagementBaseObject[])
                {
                    var jsonArray = new JArray();
                    var array = (ManagementBaseObject[])p.Value;
                    foreach (var q in array)
                    {
                        var child = new JObject();
                        foreach (var childProp in q.Properties)
                            child.Add(childProp.Name, new JValue(childProp.Value));
                        jsonArray.Add(child);
                    }
                    jo.Add(p.Name, jsonArray);
                }
                else if (p.Value != null && p.Value.GetType().IsArray)
                {
                    var jsonArray = new JArray(p.Value);
                    jo.Add(p.Name, jsonArray);
                }
                else
                {
                    jo.Add(p.Name, new JValue(p.Value));
                }
            }
            pool.Add(jo);
        }
        System.IO.File.WriteAllText("c:\\temp\\VirDirSetting.json", pool.ToString());
        Console.WriteLine(pool.ToString());
    }
}

輸出結果如下,是不是賞心悅目多了?

補充說明:以上做法適用 IIS 6 時代的 WMI 資料規則,如要在 IIS 7+使用,需安裝「IIS 6 Management Compatibility」

【延伸閱讀】

Comments

Be the first to post a comment

Post a comment