1. Qiita
  2. Items
  3. Azure

PowershellDSCでWindowsUpdateを制御

  • 6
    Like
  • 0
    Comment

複数台あるAzureの仮想マシンの管理をPowerShellDSCで行っています。
十分にテストしてからWindowsUpdateを取り込む必要がありました。
そこである特定期間までのWindowsUpdateを取り込むというスクリプトを作りました。

PSWindowsUpdateモジュール

PSWindowsUpdateというパッケージを使いました。楽したつもりがパッケージのインストールに手間取ってしまいました
以下に思いついたパッケージの導入方法をあげていきます。

PowershellGallery版

WMF5.0環境でInstall-Moduleで取り込む

https://www.powershellgallery.com/packages/PSWindowsUpdate/1.5.2.2
各ノードに5.0を導入するのに格式が高そうだったので断念。

scriptcenter版

事前にダウンロードしておいて取り込む

https://gallery.technet.microsoft.com/scriptcenter/2d191bcd-3308-4edd-9de2-88dff796b0bc
二度手間になるため断念しました。あとになって思えば初めからこれにしておけばよかったと後悔しています。

chocolatey版

4.0環境でもコマンドだけで取り込み可能

https://chocolatey.org/packages/PSWindowsUpdate
chocalteyが簡単そうだったので採用しました。
しかしDSCではなぜかchocolateyのインストールがうまくいきませんでした。
結果的に、一度Pathを通しておいて再度インストールすればなんとかインストールできることがわかりました。

実際のコードの一部

Invoke-WUScript.psm1
function Set-TargetResource
{
    [CmdletBinding()]
    param
    (
        [parameter(Mandatory = $true)]
        [ValidateSet("InvokeWUScript")]
        [System.String]
        $Name,

        [System.DateTime]
        $LastUpdateDatetime,

        [System.String[]]
        $KBArticleID,

        [System.Boolean]
        $OrLater
    )
    #モジュールがインストールされているかチェック
    ChkPSWU >$null

    Set-StrictMode -Version Latest

    #Invoke Main function
    Main -LastUpdateDatetime $LastUpdateDatetime `
         -KB $KBArticleID `
         -OrLater $OrLater

}

function Main
{
    [CmdletBinding()]
    param(
        [System.DateTime]
        $LastUpdateDatetime,
        [System.String[]]
        $KB,
        [System.Boolean]
        $OrLater
    )
    if($null -ne $KB) {
        Write-Verbose "Updates to specify the ID"
        #直接KBを指定した場合はチェック無しでインストールさせる
        Get-WUInstall -KBArticleID $KB -AutoReboot -AcceptAll
    }elseif ($null -ne $LastUpdateDatetime) {

        Write-Verbose "Updates to specify the date" 
        #日付が入っていれば、その日までの更新を取り込む
        $PatchList = Get-WUList
        if($OrLater){
            #指定日以降の更新のみに絞る
            $PatchList = $PatchList | where {$_.LastDeploymentChangeTime -ge $LastUpdateDatetime}
        }else{
            #指定日以前の更新のみに絞る
            $PatchList = $PatchList | where {$_.LastDeploymentChangeTime -le $LastUpdateDatetime}
        }

        if($null -ne $PatchList)
        {
            $PatchCounter = $PatchList.Count
            Write-Verbose "$PatchCounter of the update found"
            #if($PatchCounter -ge 1) {
            $MatchedPatchList = [string[]]($PatchList | select -Expand KB)
            Get-WUInstall -KBArticleID $MatchedPatchList -AutoReboot -AcceptAll
            #}
        }

    } else {
        throw "Parameter Not Found Error"
    }
}

function ChkPSWU
{
    try
    {        
        Write-Verbose "PSWindowsUpdateの存在チェック"
        Import-Module PSWindowsUpdate -Force -ErrorAction Stop -Verbose
    }
    catch
    {
        try
        {
            InstallPsWUModule
        }
        catch
        {

            try{
                #必要なモジュールのインストール
                InstallChoco
                InstallPsWUModule
            }
            catch
            {
                Write-Verbose $error[0].exception
                throw "PSWindowsUpdateのモジュールが存在しません。カスタムスクリプトまたは手動でインストールしてください。" 
            }
        }
    }
}
function InstallPsWUModule
{
    #なければインストール
    Write-Verbose "PSWindowsUpdateのインストール"
    choco Install PSWindowsUpdate -y

    Write-Verbose "PSWindowsUpdateモジュールのインポート"
    Import-Module PSWindowsUpdate -Force -ErrorAction Stop -Verbose
}
function InstallChoco
{
    try
    {
        Write-Verbose "chocolateyのインストール"
        (iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')))>$null 2>&1
    }
    catch
    {
        Write-Verbose "Pathを設定した上で再度インストール"
        Write-Verbose "chocolateyの環境変数を無理やり追加"
        $path = [Environment]::GetEnvironmentVariable('PATH', 'Machine')
        $path += ';' + 'C:\ProgramData\chocolatey\bin'
        [Environment]::SetEnvironmentVariable('PATH', $path, 'Machine')
        Write-Verbose "chocolateyのインストール"
        (iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1')))>$null 2>&1
    }
}
This post is the No.8 article of PowerShell Advent Calendar 2016
Comments Loading...