複数台ある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を通しておいて再度インストールすればなんとかインストールできることがわかりました。
#実際のコードの一部
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
}
}