winsowsUpdateのpowershellスクリプトについて
受付中
回答 1
投稿
- 評価
- クリップ 1
- VIEW 763
前提・実現したいこと
windowsSever2012R2のwinsowsUpdateスクリプトについて
社内サーバをwindowsserver2012R2に変更しました。
しばらく経過観察していましたが、どうも自動でwindowsUpdateが行われていないようです。
調べたところ、時間指定してのwindowsUpdateはできなく、推奨設定にするとwindowsUpdateが配信されるたびに
勝手にアップデート・再起動されてしまうことが分かりました。
社内で使用しているものなので、突然リブートがかかってしまうのは困るということで、
- windowsUpdateを見つけてインストール・ダウンロードするスクリプトをpowershellで組んで
- batファイルで動かし
- (2を)タスクスケジューラから時間指定で起動させる
手順を行いたいと考えています。
先人が作ったサンプルを拾ったのですが、powershellの経験が皆無のため調べながら改変しています。
しかし、内容が分からない部分があるので解決したいです。
分からない部分のほかに、改変したものにコメントもつけているので、間違った解釈をしているものがあれば指摘してくれたら助かります。
該当のソースコード
# 例外キャッチのデフォルト設定(ないと例外キャッチしてくれない)
$ErrorActionPreference = "Stop"
# 引数のメッセージを時刻と一緒にログに書き込むfunction
function write_log($Message)
{
$date = (Get-Date).ToString("yyyyMMdd_HHmmss")
$output = $date + " " + $Message
$output | Out-File <# ログのパス #> -Append -Encoding utf8
}
try{
write_log("Check updates Start")
# アップデートのダウンロード(開始)
$updateSession = new-object -com "Microsoft.Update.Session" # MicrosoftUpdateSessionオブジェクトのインスタンス化(new-object)
$keyWord = "IsInstalled=0 and Type='Software' and BrowseOnly = 0" # 検索キーワード
$updates = $updateSession.CreateupdateSearcher().Search($keyWord).Updates # アップデートセッションから検索キーワードに合致しているものを探し出す
$downloader = $updateSession.CreateUpdateDownloader() # アップデートセッションからダウンローダーを取得(変数化)
$downloader.Updates = $Updates # updateSearcher().Search($keyWord)から引っ張ったアップデートをダウンロード?(ここでダウンロードしているの?)
# 変数.Updatesの挙動が分からない・・・
write_log("Check updates End")
# アップデートのダウンロード(終了)
# アップデートが見つかった時の処理(なかった場合はリブートかけて終了)
if ($downloader.Updates.Count -ne "0") {
# 利用できるアップデートのインストール
write_log("Downloading " + $($downloader.Updates.count) + " updates")
$resultcode= @{0="Not Started"; 1="In Progress"; 2="Succeeded"; 3="Succeeded With Errors"; 4="Failed" ; 5="Aborted" } # ステータスのハッシュ
$Result= $downloader.Download() # ダウンロード2回目?
# アップデートできる状態なら行う?(Hresultとは・・・)
if (($Result.Hresult -eq 0) -and (($result.resultCode -eq 2) -or ($result.resultCode -eq 3)) ) {
$updatesToInstall = New-object -com "Microsoft.Update.UpdateColl" # UpdateCollのインスタンス化
foreach ($Update in $Updates | where {$_.isdownloaded} ){
$updatesToInstall.Add($Update) | out-null # アップデートファイルの追加?$updatesToInstallってインスタンスの変数じゃないの?
write_log($Update.Title)
}
$installer = $updateSession.CreateUpdateInstaller() # インストーラの宣言
$installer.Updates = $updatesToInstall
write_log("Update Install Start")
$installationResult = $installer.Install() # アップデートのインストール
write_log("Update Install End")
# リブート
if ($autoRestart -and $installationResult.rebootRequired) {
write_log("Status is Reboot Required. Reboot Start")
Restart-Computer -Force # -Forceオプションで強制リブート
Exit
} # リブートif/
} # if/
} # if/
} # try/
# 例外発生時、ログにエラー発生の旨を吐く
catch{
write_log("Windows Update Error")
}
特にわからない部分
1.$downloader.Updates = $Updatesの部分など、変数宣言時の「変数.Updates」の挙動
2.($Result.Hresult -eq 0) の「変数名.Hresult」の挙動
3.$updatesToInstall = New-object -com "Microsoft.Update.UpdateColl"でcomオブジェクトが入った変数に
$updatesToInstall.Add($Update)で配列のように別のオブジェクトを追加している理由
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
+1
今更かもしれない上にかなり推測が含まれていますが....
まず 1. を説明するために
$updates
の中身を説明します。
$updates = $updateSession.CreateupdateSearcher().Search($keyWord).Updates
ですが
最初の.CreateupdateSearcher()
でアップデートの一覧リストから必要なものを検索するオブジェクトを生成しています。
次に先ほど生成したオブジェクトを使い.Search($keyWord)
で$keyWord
に一致するアップデート項目を検索しています。
その結果は お店で売っている商品が 箱の中に本体と取り扱い説明書が入っているように
専用のオブジェクト...箱に入った状態で帰ってきます。
欲しいのは "本体" ですから箱から.Updates
でアップデート項目の配列だけを取り出しています。
ここで確認ですが、アップデート項目 は一覧リストから取得したただの表です。アップデータデータそのものではありません。
もう分かっている思うのですが
1.$downloader.Updates = $Updates
はダウンローダーにダウンロードするリストを渡しているだけで
まだ ダウンロードは行われていません。
ダウンロードの開始は$Result= $downloader.Download()
で行われています。
ここからは こちらでアップデートしていないものがなく確認できなかったので推測になります。
2.ですが
まず 先ほどの$Result= $downloader.Download()
説明ですが
$Result へはダウンロードしたデータではなく ダウンロードを実行してどうだったのかが入っていると思われます。
$Result.Hresult -eq 0
は正常に完了しているのかを確認しているのでしょう
$Result.Hresult
から0 以外が帰ってきたら失敗しているということだと思います。
一応なぜ$Result
はダウンロードしたデータでは無いと思ったかについてですが
最初に検索条件を インストール済みに変えて アップデート項目 をいくつか取得してみました。
アップデート項目の中にはIsInstalled
という項目があります。
読んで字のごとくダウンロード済みか? ということですね 普通に考えれば ダウンロードしたデータがどこに保存されるの決まってないとそんなの確認できないですよね ダウンローダーも専用のものですし
3.ですが
こちらは1と同じですね
$Update
の大本は$Updates
$Updates
は最初に説明しましたがただのリストです。
$Updates
は複数項目ですのでひと項目つづつ$Update
.Add($Update)
でセットしています。
アップデート項目を =
でセットしているのと .Add()
でセットしている違いは
変数 か メソッド(命令) なのか の違いですね
ダウンローダーさんは
<ダウンローダー >「そこに説明書を置いといてくれっ」
って感じで 既定の場所に置いといてあげれば必要な時(実行時)勝手に読んでくれるのに対して
インストーラーちゃんには
<あなた>「これを見てやってねっ」
っと手渡しで渡してあげてる感じです....
リストを渡しているだけなのでちゃんと後で
$installationResult = $installer.Install()
を実行して
<あなた>「さっき説明した内容をやってねっ」
っとしているわけですね
$installationResult
には1.と同様に実行結果が入っていると思います。
そこで.rebootRequired
を使い このインストールは 完了するために再起動が必要か確認しているのでしょう
ひとつ 気になったのですが $autoRestart
と自動変数(powershellが自動で用意してくれている変数)ではないとおもうので
あなたが インストールの完了後に自動で再起動するのかどうか決めるための項目だと思います。
自動で再起動したい場合には 行頭に
'$autoRestart = $true'
そうでない場合は
'$autoRestart = $false'
と追加した方がいいと思います
変数の初期値は$null bool値に変換すると$false
と同様に扱われてしまうので
if ($autoRestart -and $installationResult.rebootRequired)
の結果が必ず`$false'になってしまうので
いつまでたっても インストール完了後に再起動が実行されません。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。