2014/09/10

Windows Server の主な設定値を PowerShell で取得して CSV で出力する

Introduction

インフラ構築って仕事をやっていると、いまだに土方作業っぽいところがある。
方眼紙エクセルで作られた詳細設計書と実機設定の突合せなんかがまさにそれ。
Windows な現場が多いんで、GUI で設定値確認してスクリーンショットでエビデンス取得。
はい、それ 80 台やっといてとか、もう。。。人間のやる仕事じゃないでしょ。

ってことで、自動化しましょう。
Desired State Configuration(DSC)でやるのが流れなんだろうけど、いったん置いといて PowerShell でスクリプト書くよ。
個人的な趣味として組み上げたので、実行については自己責任で。 実行方法とかはよそ様のブログや Technet 参照ってことで。UAC は無効化、管理者実行は基本です。

こんなスクリプトにしたい

  • Windows Server のメジャーな設定項目の値を自動で取得する
  • 設定値を取得したら、テキスト(CSV)で出力する
    • 後々ここで取得した情報から設計書を作成したいから
  • Windows 2008R2, 2012 の標準コンポーネントだけで動かなきゃだめ
基本は WMI オブジェクトで取得していきます。
どうしても WMI で取れないものはレジストリをで取得、それもだめなら exe コマンドの出力結果をごにょごにょやります。 
WMI クラスの意味は MSDN で公開されています↓(英語のみ) 
 http://msdn.microsoft.com/en-us/library/aa394572%28v=vs.85%29.aspx
公式ではないけれど、日本語版↓
http://www.wmifun.net/library/

スクリプト内関数とか

ログの出力
$LogPath = "C:\hoge\fuge"
function Out-LogFile ($p1,$p2){
    $CSVFilePath = Join-Path $LogPath ($p2 + ".csv")
    $p1|Export-Csv -Path $CSVFilePath -NoTypeInformation -Encoding UTF8
    #コンソール 画面出力
    $p1


Windows 2008 R2 標準の PowerShell 2.0 の Export-Csv には -Append (追記書き)オプションがない。
オブジェクトをまるっと出力する場合この関数でよいが、foreach で回して一行づつ追記していくような処理はできない。
それに対応した関数も用意しておく。

function Out-LogFile_ConvertVer($p1,$p2){
$CSVFilePath = Join-Path $LogPath ($p2 + ".csv")
    #ヘッダー出力判定
    if( -not (test-path $CSVFilePath)){
        # CSV が存在しないときはヘッダー行含めて出力
        (ConvertTo-Csv -InputObject $p1 -NoTypeInformation -Delimiter ",")|Out-File $CSVFilePath -Encoding utf8 -Append
    }else{
        # CSV が存在する時は値のみ出力
        (ConvertTo-Csv -InputObject $p1 -NoTypeInformation -Delimiter ",")[1]|Out-File $CSVFilePath -Encoding utf8 -Append
    }
    #コンソール 画面出力
$p1
}

設定値取得

OS 基本設定を取得してく
# OS 基本情報とコンピューターの基本情報を WMI オブジェクトで取得
$OSInfo = Get-WmiObject -NameSpace root\CIMV2 -Class Win32_OperatingSystem
$CompInfo = Get-WmiObject -NameSpace root\CIMV2 -Class Win32_ComputerSystem

# 情報集積用の空オブジェクト作成 OS基本情報用
$Computer = New-Object psobject

# 基本情報から必要なプロパティを集積用の空オブジェクトのプロパティとして追加
$Computer|Add-Member -MemberType NoteProperty -Name 'ホスト名' -value $Env:COMPUTERNAME
$Computer|Add-Member -MemberType NoteProperty -Name 'OS 名' -value $osinfo.Caption
$Computer|Add-Member -MemberType NoteProperty -Name 'SP レベル' -value $osinfo.CSDVersion
$Computer|Add-Member -MemberType NoteProperty -Name 'OS バージョン' -value $osinfo.Version
$Computer|Add-Member -MemberType NoteProperty -Name 'OS ビルド' -value $osinfo.BuildNumber
$Computer|Add-Member -MemberType NoteProperty -Name 'ドメイン参加' -Value $CompInfo.PartOfDomain
#ドメイン参加orワークグループ判定
switch($CompInfo.PartOfDomain){
  $true {$domname = $CompInfo.Domain}
  $false {$domname = $CompInfo.Workgroup}
  default {$domname = "はじまったな。。。ああ。。"}
}
$Computer|Add-Member -MemberType NoteProperty -Name 'ワークグループ/ドメイン名' -value $domname
$Computer|Add-Member -MemberType NoteProperty -Name '物理メモリサイズ' -value ([string]((Get-WmiObject -NameSpace root\CIMV2 -Class Win32_PhysicalMemory).capacity / 1024000000)+" GB")
$Computer|Add-Member -MemberType NoteProperty -Name 'ユーザーが利用できるメモリサイズ' -Value ([string]($osinfo.TotalVisibleMemorySize / 1024000) + " GB")
#RemoteDesktop 設定取得 レジキーでとって、スイッチ文で判定
$RDP = Get-WmiObject -NameSpace root\CIMV2\TerminalServices -Class Win32_TerminalServiceSetting
switch($RDP.AllowTSConnections){
    0{$RDPEnabled = "無効"}
    1{$RDPEnabled = "有効"}
    default{$RDPEnabled = "姉さん、事件です。"}
}
$Computer|Add-Member -MemberType NoteProperty -Name 'リモートデスクトップ' -Value $RDPEnabled

#時刻同期設定取得
$TimeZone = (Get-Wmiobject -NameSpace root\CIMV2 -Class Win32_TimeZone).caption
$NTP_Param = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Parameters
$NTP_Cliant = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\TimeProviders\NtpClient
$NTP_Config = Get-ItemProperty HKLM:\SYSTEM\CurrentControlSet\services\W32Time\Config
switch($NTP_Cliant.Enabled){
    0{$NTP_Cliant.Enabled = "無効"}
    1{$NTP_Cliant.Enabled = "有効"}
    default{$NTP_Cliant.Enabled = "僕と契約して、NTPサーバーになってよ!"}
}
$Computer|Add-Member -MemberType NoteProperty -Name 'タイムゾーン' -Value $TimeZone
$Computer|Add-Member -MemberType NoteProperty -Name '時刻同期タイプ' -Value $NTP_Param.Type
$Computer|Add-Member -MemberType NoteProperty -Name '同期先 NTP サーバー' -Value $NTP_Param.NtpServer
$Computer|Add-Member -MemberType NoteProperty -Name 'NTP クライアント有効/無効' -Value $NTP_Cliant.Enabled
$Computer|Add-Member -MemberType NoteProperty -Name 'SpecialPollInterval' -Value ([string]($NTP_Cliant.SpecialPollInterval) + " 秒 (" + [string]($NTP_Cliant.SpecialPollInterval / 60 / 60 /24) + " 日)" )
$Computer|Add-Member -MemberType NoteProperty -Name 'MinPollInterval' -Value ([string]($NTP_Config.MinPollInterval) + " 秒")
$Computer|Add-Member -MemberType NoteProperty -Name 'MaxPollInterval' -Value ([string]($NTP_Config.MaxPollInterval) + " 秒")



こんな感じでどんどん追加していく。

#UAC 取得

#次の場合は常に通知する
#ConsentPromptBehaviorAdmin = 2 (Vista での既定値)
#PromptOnSecureDesktop = 1
#EnableLUA = 1

#プログラムがコンピューターに変更を加えようとする場合のみ通知する(7,2008R2 既定値)
#ConsentPromptBehaviorAdmin = 5
#PromptOnSecureDesktop = 1
#EnableLUA = 1

#プログラムがコンピューターに変更を加えようとする場合のみ通知する(デスクトップを暗転しない)
#ConsentPromptBehaviorAdmin = 5
#PromptOnSecureDesktop = 0
#EnableLUA = 1

#以下の場合でも通知しない
#ConsentPromptBehaviorAdmin = 0
#PromptOnSecureDesktop = 0
#EnableLUA = 0

$uac = Get-ItemProperty HKLM:Software\Microsoft\Windows\CurrentVersion\policies\system
$Computer|Add-Member -MemberType NoteProperty -Name '昇格時のプロンプトの動作' -Value $uac.ConsentPromptBehaviorAdmin
$Computer|Add-Member -MemberType NoteProperty -Name 'デスクトップの暗転' -Value $uac.PromptOnSecureDesktop
$Computer|Add-Member -MemberType NoteProperty -Name 'UAC EnableLUA' -Value $uac.EnableLUA

#自動更新設定取得
$WindowsUpdateAU = Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update"
$WindowsUpdatePol = Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate"
$WindowsUpdatePolAU = Get-ItemProperty "HKLM:\SOFTWARE\Policies\Microsoft\Windows\WindowsUpdate\AU"
 

if($WindowsUpdateAU -ne $null){
    Switch($WindowsUpdateAU.AUOptions){
        0{$WUAU = "未構成"}
        1{$WUAU = "更新プログラムを確認しない"}
        2{$WUAU = "更新プログラムを確認するが、ダウンロードとインストールを行うかどうかは選択する"}
        3{$WUAU = "更新プログラムをダウンロードするがとインストールを行うかどうかは選択する"}
        4{$WUAU = "更新プログラムを自動的にインストールする"}
        $null {$WUAU = "未構成"}
        default{$WUAU = "あなたは死なないわ。私がアップデートするもの。"}
    }
    Switch($WindowsUpdateAU.UseWUServer){
        0{$UseWU = "使わない"}
        1{$UseWU = "使う"}
        default{$UseWU = "使わない"}
    }
}


if($WindowsUpdatePolAU -ne $null){
    Switch($WindowsUpdatePolAU.NoAutoUpdate){
        0{$NoAU = "有効"}
        1{$NoAU = "無効"}
        default{$NoAU = "あなたは死なないわ。私がアップデートするもの。"}
    }
}else{
    $NoAU = "未構成"
}

if($WindowsUpdatePolAU -ne $null){
    Switch($WindowsUpdatePolAU.AUOptions){
        0{$AUop = "未構成"}
        1{$AUop = "自動更新を無効にする"}
        2{$AUop = "更新を通知するのみで、自動的なダウンロードまたはインストールを実行しない"}
        3{$AUop = "更新を自動的にダウンロードするが、インストールは手動で実行する"}
        4{$AUop = "推奨される更新を自動的にダウンロードし、指定した時刻にインストールする"}
        $null{$AUop = "未構成"}
        default{$AUop = "あなたは死なないわ。私がアップデートするもの。"}
    }
}else{
    $AUop = "未構成"
}

if($WindowsUpdatePol -ne $null){
  $WUServer =  $WindowsUpdatePol.WUServer
  $WUStatusServer = $WindowsUpdatePol.WUStatusServer
}else{
    $WUServer = $WUStatusServer = "未構成"
}

$Computer|Add-Member -MemberType NoteProperty -Name '自動更新設定(ローカル)' -Value $WUAU
$Computer|Add-Member -MemberType NoteProperty -Name 'WSUS サーバーを使う' -Value $UseWU
$Computer|Add-Member -MemberType NoteProperty -Name '自動更新有効/無効(WSUS)' -Value $NoAU
$Computer|Add-Member -MemgberType NoteProperty -Name '自動更新設定(WSUS)' -Value $AUop
$Computer|Add-Member -MemberType NoteProperty -Name 'Windows Update 参照先' -Value $WUServer
$Computer|Add-Member -MemberType NoteProperty -Name 'Windows Update レポート報告先' -Value $WUStatusServer



まだまだあるんだけど、省略!
#そのうち Github で公開するつもりです。
で、最後にオブジェクトを出力
#OS基本情報出力
Out-LogFile $Computer "OS基本情報"

こんな感じで CSV が生成されます。(OS基本情報.csv)

今回はこんなとこで。使っていない関数は次回

0 件のコメント:

コメントを投稿