[PowerShell] プレビュー版の PowerShell 7 がMicrosoft Update経由での自動更新に対応しました

2021.06.28

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

しばたです。

先日PowerShell Teamから以下のブログが公開されプレビュー版のPowerShell 7 (PowerShell 7.2-preview.7) がMicrosoft Updateによる自動更新に対応したとアナウンスされました。

本記事ではこの内容に関してPowerShell特有の事情を交えながら解説します。

様々な PowerShell 7 とその更新方法

まず最初に現状のPowerShell 7が抱える事情について解説します。

2016年にPowerShellがオープンソース化しPowerShell Coreとなった当初はGitHubでインストーラーが公開され、ユーザーはGitHubからインストーラーをダウンロードし手動インストールする必要がありました。
その後macOSやLinuxでは各OSで使われるパッケージマネージャーからのインストールにも対応し、Windows環境においてはMicrosoft Store版のPowerShell 7も追加されています。

本日時点でのWindows環境におけるPowerShell 7のインストール方法は以下となります。

方式 Stable版 Preview版 自動更新 備考
MSIインストーラー × GitHubのリリースページからダウンロード
Zipファイルを展開 × GitHubのリリースページからダウンロード
.NET Core Global Toolsでインストール 開発者向け
Microsoft Storeから入手 Windows 10のみ利用可能。機能面でストアアプリの制約を受ける。
Windows Package Manager (winget)から入手 Windows 10のみ利用可能(内部的にはMSIインストーラー利用)
非公式パッケージマネージャーから入手 ChocolateyやScoopなど(内部的にはMSIインストーラー利用)

「用途やユーザーからのニーズに応じて多くのインストール方法を提供した」と言えば聞こえは良いですが、正直、無節操に方式を増やしてきたと言われても仕方ない部分もあります。

ここまで多くの方式を増やすことになってしまった根本原因に「PowerShell 7をOSにプリインストールすることができない」という事情があります。

本来PowerShell 7の最終目標であり理想形は「Windows PowerShellをPowerShell 7に置き換えOSにプリインストールする」です。
これが未だ達成できない事情としては、PowerShell 7とWindows PowerShellの互換性が完全でないという事もありますが、一番大きな問題はPowerShell 7がWindows OS(LTSC)の要求するサポート期間を満たせない点です。

PowerShell 7およびその基盤となる.NET Coreは長期リリース版(LTSバージョン)でも3年程度のサポートなのですが、Windows OSが要求するサポート期間は5年 *1であり、この差を埋める方式を決めることができず現状に至っています。

この事情により良くも悪くもPowerShell 7には様々なインストール方式が存在しています。

Microsoft Update経由での自動更新に対応する意図

今回のアナウンスでMSIインストーラーでインストールしたプレビュー版PowerShell 7をMicrosoft Updateにより自動更新できる様になったとのことですので前掲の表に合わせた表記をすると以下の様な感じになります。

現時点で自動更新できるのはプレビュー版のみです。Stable版は対応してません。

方式 Stable版 Preview版 自動更新 備考
MSIインストーラー : Microsoft Updateによる更新 × PowerShell 7.2-preview.7以降で可能

今回Microsoft Updateによる更新が増えた動機としては

But with Microsoft Update, you’ll get the latest PowerShell 7 updates directly in your traditional Windows Update (WU) management flow, whether that’s with Windows Update for Business, WSUS, SCCM, or the interactive WU dialog in Settings.

と、公式には従来のWindows Updateによる更新やWSUSやSCCMによる管理下に置くことが語られています。
これまでの一般ユーザーや開発者向けというよりはシステム管理者の統制目的の要素が強い印象を受けます。

Microsoft Updateによる更新は前節で述べた最終目標とも関連があるため、Stable版が対応するころにはPowerShell 7(またはその先のバージョン)がOSにプリインストールされるかについても進展があることでしょう。
アナウンスで直接触れられていないものの、将来のOSプリインストールへの準備もその意図に含まれると私は見ています。

試してみた

前置きはこの程度にしてここからは実際に試してみます。

前提条件

今回の更新を試すには以下の環境である必要があります。

  • Windows 10 RS3 (Build 10.0.16299) 以降のバージョン
    • ブログでは明言されませんでしたが、Windows Server 2019でも動作しました
  • PowerShell 7が以下の形でインストール済みであること
    • PowerShell 7のStable版のみインストールされている
    • PowerShell 7のStable版 + PowerShell 7.2.preview-5 ~ PowerShell 7.2.preview-6 がインストールされている

後者の条件が意図したものなのかバグなのか不明ですが、現状Stable版のPowerShell 7がインストールされていないとプレビュー版の自動更新ができません。
(一応GitHubのdiscussionで聞いてみてますが、正直私はバグだと思っています...)

これらの条件に加え、Microsoft Updateによる更新をオプトインしなければなりません。

【追記】PowerShell 7 Stable版がインストールされていない場合の回避策

GitHub discussionで回答いただき、PowerShell 7 Stable版がインストールされていない環境では以下のコマンドを実行してあたかもStable版がインストールされているかの様に見せかけることでも対応可能とのことです。

# InstalledVersions\31ab5147-9a97-4452-8443-d9709f0516e1 のキー (Stable版のキー) を作ることでStable版がインストール済みかの様に見せる
$pwshRegPath = "HKLM:\SOFTWARE\Microsoft\PowerShellCore"
$stablePath = Join-Path -Path $pwshRegPath -ChildPath "InstalledVersions\31ab5147-9a97-4452-8443-d9709f0516e1"
if (!(Test-Path -Path $stablePath)) {
    $null = New-Item -Path $stablePath -ItemType Directory -Force
}

一応現在の挙動はバグらしいので将来のリリースではこの前提条件は改善されると思われます。

検証環境

今回は個人の開発環境に作ったWindows 10 VMで試しました。

  • 64bit版 Windows 10 21H1 (Build 10.0.19043)
  • PowerShell 7.1.3 (MSIインストーラー) インストール済み

PowerShell 7.1.3のインストール手順については割愛しますが、必ずMSIインストーラーでインストールする必要があります。

1. PowerShell 7側の設定変更

最初にPowerShell Team Blogで紹介されている様にPowerShell 7側のレジストリ設定を変えて自動更新をオプトインする必要があります。

管理者権限のあるユーザーで以下のコマンドを実行しレジストリキーを更新してください。

$pwshRegPath = "HKLM:\SOFTWARE\Microsoft\PowerShellCore"
$previewPath = Join-Path -Path $pwshRegPath -ChildPath "InstalledVersions\39243d76-adaf-42b1-94fb-16ecf83237c8"
if (!(Test-Path -Path $previewPath)) {
    $null = New-Item -Path $previewPath -ItemType Directory -Force
}

Set-ItemProperty -Path $pwshRegPath -Name UseMU -Value 1 -Type DWord
Set-ItemProperty -Path $previewPath -Name Install -Value 1 -Type DWord

  • HKLM:\SOFTWARE\Microsoft\PowerShellCore\UseMU = 1 にする

今回プレビュー版のPowerShell 7を未インストールの状態なので追加で

  • HKLM:\SOFTWARE\Microsoft\PowerShellCore\InstalledVersions\39243d76-adaf-42b1-94fb-16ecf83237c8\Install = 1 にする

もやっています。

PowerShell 7.2.preview-5以降をインストール済みであればこのキーは作らなくて大丈夫です。

2. Windows Updateの設定変更

次にWindows Updateの設定を変更します。
Windowsの「設定」から「更新とセキュリティ→Windows Update→詳細オプション」を選び、「Windowsの更新時に他のMicrosoft製品の更新プログラムを受け取る」をチェックします。

PowerShell 7は「他のMicrosoft製品」扱いとなります。

もしこの欄がグレーアウトされ変更できない場合はグループポリシーで制御されていますので適宜ポリシーを変更して対応してください。

3. 更新の確認

これで準備ができたので「Windows Update」から更新プログラムをチェックしてみます。

設定に不備がなければ「PowerShell v7.2.0-preview.7」がダウンロードされ自動インストールされます。

エラーなく終われば「PowerShell v7.2.0-preview.7」がインストール(または更新)されているはずです。

補足 : オプトアウトするには

Microsoft Updateによる自動更新をオプトアウトしたい場合は変更したレジストリキーの値を0にするかキー自体を削除してください。
PowerShell Team Blogでは値を0にするパターンが例示されていますので以下に引用しておきます。

# 管理者権限で以下のコマンドを実行してレジストリ値を更新(オプトアウト)する
$pwshRegPath = "HKLM:\SOFTWARE\Microsoft\PowerShellCore"
$previewPath = Join-Path -Path $pwshRegPath -ChildPath "InstalledVersions\39243d76-adaf-42b1-94fb-16ecf83237c8"
if (!(Test-Path -Path $previewPath)) {
    throw "PowerShell 7 Preview is not installed"
}

Set-ItemProperty -Path $pwshRegPath -Name UseMU -Value 0 -Type DWord
Set-ItemProperty -Path $previewPath -Name Install -Value 0 -Type DWord

最後に

以上となります。
今すぐ皆さんの役に立つ感じの更新ではないですがPowerShell 7の現状を踏まえながら見ると意外と面白い内容ではありました。

普段からプレビュー版のPowerShell 7を使いまくる方やWSUSなどによる統制を検討している方は今から試しておくと良さそうです。

脚注

  1. 以前は10年だったのでこれでも短くなってる