質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

Windows Server

Windows Serverとは、Microsoft社のサーバ用オペレーティングシステムの総称です。 企業内ネットワークなどで利用されるサーバ機へ導入することを想定して開発されているため高い安定性があり、 管理機能を提供するソフトウェアが多く含まれています。

Q&A

1回答

2068閲覧

winsowsUpdateのpowershellスクリプトについて

momiji214

総合スコア7

PowerShell

Windows PowerShellはコマンドラインインターフェースであり、システム管理を含むWindowsタスク自動化のためのスクリプト言語です。

Windows Server

Windows Serverとは、Microsoft社のサーバ用オペレーティングシステムの総称です。 企業内ネットワークなどで利用されるサーバ機へ導入することを想定して開発されているため高い安定性があり、 管理機能を提供するソフトウェアが多く含まれています。

0グッド

1クリップ

投稿2018/01/13 17:13

###前提・実現したいこと

windowsSever2012R2のwinsowsUpdateスクリプトについて

社内サーバをwindowsserver2012R2に変更しました。
しばらく経過観察していましたが、どうも自動でwindowsUpdateが行われていないようです。
調べたところ、時間指定してのwindowsUpdateはできなく、推奨設定にするとwindowsUpdateが配信されるたびに
勝手にアップデート・再起動されてしまうことが分かりました。
社内で使用しているものなので、突然リブートがかかってしまうのは困るということで、

  1. windowsUpdateを見つけてインストール・ダウンロードするスクリプトをpowershellで組んで
  2. batファイルで動かし
  3. (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)で配列のように別のオブジェクトを追加している理由

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

今更かもしれない上にかなり推測が含まれていますが....

まず 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'になってしまうので
いつまでたっても インストール完了後に再起動が実行されません。

投稿2018/11/16 10:27

編集2018/11/16 10:30
kamikazelight

総合スコア305

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問