なかなかパッチを適用できないサーバーがあり、そのサーバーにどのパッチが当たっていないかを確認したいと思った時のメモ。
■環境
- サーバー:Windows Server 2008 R2 + .NET Framework 3.5 SP1
- クライアント:Windows7 x86 + .NET Framework 4
.NETのバージョンは「.NET Version Detector」を使用して確認した。
窓の杜 - インストール済みの.NET Frameworkのバージョンを調査する「.NET Version Detector」
■確認方法
MicrosoftがMicrosoft Baseline Security Analyzer(MBSA)を公開しているので、それを利用する。
セキュリティ TechCenter - Microsoft Baseline Security Analyzer 2.2
インストールして実行する方法とコマンドラインは、以下を参照。ヘルプにも詳しい記載あり。
@IT - MBSAをオフラインで実行する
サーバー上に必要なファイルを置き、管理者のコマンドプロンプトで実行。
mbsacli.exe /xmlout /unicode /nd /nvc /wi /catalog wsusscn2.cab > mbsareport.xml
ちなみに、管理者のコマンドプロンプトでないと、エラーで動作しない。
参考:横着者のメモ帳 - いろいろ/VistaでMBSA2.1のmbsacliでセキュリティのCABファイルを読み込めません。
■作成したXMLファイルを見る
■作成したファイルをCSVファイルへと変換する
XMLビューワでも見ることは可能だが、CSVに変換してみる*1。
ソースコードを利用しなくても以下のようにしてExcelで見れるが、LINQ to XMLの勉強を兼ねてC#で組んでみる。
SEの雑記 - MBSA と DISM を使用した 2008 R2のパッチ適用
コンソールアプリケーションで作成。第一引数でxmlファイルのパスを引き渡すことも可能にしてみた。
ソースは以下、gist版はこちら。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Xml.Linq; namespace MBSAToCSV { class Program { static void Main(string[] args) { string xmlFilePath = ""; if (args.Any()) { xmlFilePath = args.First(); } else { xmlFilePath = @"<デフォルトのXMLファイルパス>"; } if (System.IO.File.Exists(xmlFilePath)) { } else { Console.WriteLine("ファイルがありません。"); return; } var csv = System.Xml.Linq.XElement.Load(xmlFilePath).Elements("Check").Elements("Detail").Elements("UpdateData") .Where(a => a.Attribute("IsInstalled").Value == "false") .Select(b => string.Format("{0},{1},{2},{3}{4}", (string)b.Attribute("ID"), "KB" + (string)b.Attribute("KBID"), (string)b.Element("Title"), (string)b.Element("References").Element("InformationURL"), Environment.NewLine )) .Aggregate(new StringBuilder(), (sb, s) => sb.Append(s), sb => sb.ToString()); // 拡張子をxmlからstringに変換して保存 string csvPath = xmlFilePath.Substring(0, xmlFilePath.Length - 3) + "csv"; System.Text.Encoding enc = System.Text.Encoding.GetEncoding("shift_jis"); using (System.IO.StreamWriter sw = new System.IO.StreamWriter(csvPath, false, enc)) { // ヘッダーの先頭にID列を表記したい場合はダブルコーテーションで囲む // See: http://pasofaq.jp/office/excel/sylk.htm string header = "\"ID\",KB番号,タイトル,情報へのURL"; sw.WriteLine(header); sw.WriteLine(csv); } Console.WriteLine("出力しました。"); } } }