• 記事
  • Windows Updateの状態をコマン...
 Windows Updateの状態をコマンドラインから調べる方法を考える

Windows Updateの状態をコマンドラインから調べる方法を考える

 Windows Updateは、毎月のように品質アップデートがあり、その中には再起動を要求するものもの少なくない。とはいえ、頻繁に設定のWindows Updateを見るのも億劫だ。そこで、コマンドラインからWindows Updateの状態をチェックできるかを考えてみた。それが可能なら、たとえばタスクスケジューラーなどで定期的に実行することも可能になる。また、スクリプトを作れば、さまざまな形で通知できる。

Windows Update Agent APIを使うと、Windows Updateに関する情報を引き出すことができる。これは、再起動待ちのアップデートを検出した例。Windows 11の「設定」→「Windows Update」で再起動の保留中になっているプレビュー版を、上記のスクリプトが検出している

Windows Updateは大きく3つに分類できる

 Windows Updateについては、この連載でも何度か取り上げたが、概要に関しては、以下の記事を参照されたい。

●Windows Updateを飼い慣らして、都合のいい時間に再起動させる方法
 https://ascii.jp/elem/000/004/045/4045886/

 Windows Updateには、いろいろなものがあるが、状態をチェックするという視点からみると、大きく以下の3つに分類できる。

1. 勝手にインストールして終わるもの(再起動不要)
2. インストール完了後に再起動が必要になるもの
3. インストールを完了するために再起動が必要になるもの(インストールは未完了)

 1はたとえば、ウイルス定義のアップデートなどだ。この場合、勝手にダウンロード、インストールが進んで終了してしまうので、特に検出する必要もないし、そもそもよほど短い間隔でチェックを繰り返さないと検出が難しい。

 2と3は、インストールが自動の場合とユーザーが開始を指示しないとインストールされない場合があるのだが、現在のWindows 10では、ダウンロードに関しては自動で行なわれるようだ。ただし、品質アップデートのように大きなものは、ユーザーがダウンロードの開始を指示する必要がある。

 また、Windows Updateの設定により、インストールが自動で開始されることもある。具体的には「設定」→「Windows Update」→「詳細オプション」にある「更新プログラムをインストールするために再起動が必要な場合は、できるだけすぐにこのデバイスを再起動してください。以下略」という長い名前のトグルスイッチをオンにした場合だ。

 再起動が必要なWindows Updateは、複数の再起動が必要なアップデートがあったとしても、そのうちの1つでも作業を完了すると、ユーザーに再起動を促す。しかし、可能性としてまだ他のアップデートのインストールが完了していない場合がある。とはいえ、少なくとも再起動に関しては、タスクバーの通知領域やアクションセンターでの通知がある。

 これに対して、再起動要求の有無にかかわらず、インストールが進行中の場合、設定のWindows Updateのページを見ないことには何もわからない。今回はこれを検出することにしたい。

Windows Update Agent APIを使う

 Windows Updateに関する情報は、Windows Update Agent APIから入手できる。なお、このAPIは、COMなので、PowerShellなどからもアクセスが可能だ。ここでは、Windowsに標準で含まれるWindows PowerShellを使い、このAPIにアクセスしてみる。

 Windows Updateの状態をコマンドラインから調べる方法を考える

●Windows Update Agent API(英語)
 https://docs.microsoft.com/en-us/windows/win32/api/_wua/

 プログラミングに関する細かい話には、おそらく多くの人が興味がないだろうから、現在Windows Updateが管理しているアップデートのリスト(インストール前のものと、インストール済みのもの)を入手する方法を示す。

リスト1

$WindowsUpdateSearch=(New-Object -ComObject Microsoft.Update.Session).CreateUpdateSearcher();
$update=$WindowsUpdateSearch.Search("IsInstalled=0 OR IsInstalled=1").updates;

 1行目でCOMオブジェクト“Microsoft.Update.Session”(これがWindows Update Agentオブジェクト)を作り、そこからアップデートを検索するための「UpdateSearcher」を作成する。2行目は、作成されたUpdateSearcherに検索条件("IsInstalled=0 OR IsInstalled=1")を渡して、Updatesオブジェクトを作成するものだ。何も条件を指定しないと"IsInstalled=0"か指定されたのと同じ結果が得られる。前記のURLを見る気も起きないような場合には、これをおまじないと思って使ってかまわない。

 2行目でUpdatesオブジェクトは、$updateという変数に保存したので、以後は、この$updateを使う。というのは、検索には1分ほど時間がかかることがあるので、毎回検索すると時間が掛かりすぎるからだ。ただし、Windows Updateの最新情報を得るためには、2行目を再度実行しなければならない。とはいえ、Windows Updateのデフォルトの更新は1日1回程度、つまり1日に数回繰り返して実行すればよい。

 Updatesオブジェクトには「設定」→「更新とセキュリティ」→「Windows Update」(Windows 11は「設定」→「Windows Update」)に表示されるWindows Updateを保持している。状態を確認するのに必要なプロパティには以下のようなものがある。

プロパティ名意味ドキュメント
IsInstalledアップデートはインストールされたhttps://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdate-get_isinstalled
IsDownloadedアップデートはダウンロードされたhttps://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdate-get_isdownloaded
RebootRequired再起動が必要https://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdate2-get_rebootrequired
IsPresentアップデートが存在しているhttps://docs.microsoft.com/en-us/windows/win32/api/wuapi/nf-wuapi-iupdate2-get_ispresent

 前述のように、アップデートには3種類あり、検出するのは、再起動が必要なアップデートが進行中なのか、インストールが完了して再起動待ちなのかどうかという点。これには、Windows Update Agentでアップデートを検索し、そのプロパティを調べる。まずはアップデートが進行中の場合、プロパティは以下の状態となる。

IsInstalled = false
IsDownloaded =true
RebootRequired = false

 なお、実際にやってみたところ、すでにインストールが完了しているのにもかかわらず、アップデートが未インストールとして表示されるものがあったので、以下の条件を追加した。

IsPresent = false

 これを検出するには、PowerShellのWhere-Objectを使い、以下のリストのように実行する。

リスト2

$update | Where-Object {$_.isinstalled -eq $false -and $_.isdownloaded -eq $true -and $_.rebootrequired -eq $false -and $_.isPresent -eq $false} | Select-Object title

※ $updateは、リスト1で設定している

 もし、この条件を満たすアップデートがあれば、その時点で1回は設定のWindowsアップデートのページを確認したほうがいいだろう。場合によっては、ユーザーからのインストール指示待ちになっていることがある。また、すでに再起動の要求が出ていたとしても、この状態を満たすアップデートがあるなら、別のアップデートが進行中である。

 なお、アップデートはユーザーが指示するなどして、インストールが開始されると、2つの状態になる。1つは前述の「2」で、この場合、「IsInstalled」と「RebootRequired」がtrueとなる。もう1つは、前述の「3」で、こっちは「IsInstalled」はfalseのままだが、「RebootRequired」がtrueとなる。この2つを検出するには、以下のリストのコマンドを使う。

リスト3

$update | Where-Object {$_.rebootrequired -eq $true} | Select-Object title

※ $updateは、リスト1で設定している

 これらの条件をまとめたのが、以下の表だ。

 表の最初の3つが、インストールが完了していないアップデートだが、この中には、まだ何もしていないもの(表の一番上の行)と、すでにインストールしているにもかかわらず、再度通知が来たもの(2行目)があり、これらを区別するために3行目の条件を指定する必要がある。これに対して、再起動を要求しているアップデート(4、5行目)は、再起動が行なわれていないため、インストールが完了していない。