セイテクエンジニアのブログ かつて山市良と呼ばれたおじさんのブログ vol.10 もう1つのPowerShellサンプル「Resize_Script.ps1」とは
2024年05月16日配信
2024年11月07日更新
執筆者:山内 和朗
WinRE問題に関連しては、前々回と前回に取り上げたMicrosoft提供のPowerShellスクリプト「PatchWinREScript_General.ps1」も美味しそうでしたが、同じ問題に関連して公開されたもう1つのスクリプト「Resize_Script.ps1」もまた、美味しそうな香りがします。今回もまた、最初にスクリプトそのものを実行して、どんなものなのか体験してみました。前にも言いましたが、“サンプル”と謳っているため、十分に検証されておらず、バグが存在するかもしれません。なので、”皆さんもご一緒に...”とは決して言いません。
vol.8とvol.9で取り上げたPowerShellスクリプトのサンプルは、今年初めてのWindows Updateの更新プログラムリリース日と同じ2024年1月9日(米国時間)にMicrosoftが公開したものです。このサンプルスクリプトによるWinREのオフラインパッチを自動化ソリューションとして、一部のWindows 10/11バージョンとWindows Server 2022にWinREのセキュリティ更新プログラムをリリースし、それが回復パーティションの空き容量不足が原因でエラーで失敗するという問題を一部の環境で発生させました。
今回紹介するPowerShellスクリプトのサンプル「Resize_Script.ps1」は、多くのエンドユーザーにとっては難しいであろう、DISMコマンドを使用した回復パーティションのサイズ拡張作業を、自動的に行ってくれるものです。このサンプルスクリプトは以下のドキュメントページからプレーンテキストとしてコピーすることができます。
Windows RE に更新プログラム パッケージを追加する|Windows REのパーティションを拡張する
https://learn.microsoft.com/ja-jp/windows-hardware/manufacture/desktop/add-update-to-winre#extend-the-windows-re-partition
しかし、コマンドプロンプト(管理者)の操作に慣れていない人にとっては、PowerShellのスクリプトを実行する操作も難しいでしょう。PowerShellの実行ポリシーの変更が必要かもしれませんし、空のバックアップフォルダーを用意する必要もあります。カレントディレクトリに保存したのに、ドキュメントどおりのコマンドラインを入力しても実行されないことに悩むかもしれません。
良い点があるとすれば、ディスク番号やパーティション番号を調べたり、それに合わせてDISKPARTコマンドを間違いなく入力したり(絶対にミスできない部分)する必要がないこと。ただし、それはこのスクリプトに重大なバグがなく、期待通りに動くことが前提です。
勘違いされがちなのが、「PatchWinREScript_General(または2004plus).ps1」や「Resize_Script.ps1」のいずれか一方を実行して、WinREのセキュリティ更新プログラムのエラーを解決をできたつもりになってしまうことです。「PatchWinREScript_General(または2004plus).ps1」は、あくまでもWinREのセキュリティ更新プログラムや累積更新プログラムが提供されていないWindowsバージョンで(Windowsのバージョンに依る)、手動でWinREにある脆弱性を解決するものであり、WinREのセキュリティ更新プログラムのエラーを解決するものではありません。「Resize_Script.ps1」はWinREのセキュリティ更新プログラムのエラーや「PatchWinREScript_General(または2004plus).ps1」スクリプトのエラーを解決するものですが、回復パーティションのサイズを拡張するだけのものです。
最初に、Windows 10をクリーンインストールした環境で「Resize_Script.ps1」を実行してみました。Windows 10をクリーンインストールした環境で自動作成されるパーティション構成では、回復パーティションの空き容量不足でWinREのセキュリティ更新プログラム(KB5034441)のインストールがエラーで失敗します。(※KB5034441はKB5042320《外部サイト》に置き換えられました)
Windows PowerShell(管理者)のウィンドウを開き、「Resize_Script.ps1」として保存したサンプルスクリプトを実行します。カレントディレクトリに「Resize_Script.ps1」がある場合は、次のように実行します。空の作業フォルダー(空である必要があります)のパスは一例です。
画面2 スクリプトの実行が成功すると、回復パーティションのサイズはちょうど250MB(589MB+250MB)が増加した
サンプルスクリプトはまず、WinREの状態を調べ、無効になっている場合は何もせず終了します。WinREが有効な場合、OSドライブ(通常、C:ドライブ)とそのパーティション情報、WinREの場所とそのパーティション情報を調べ、空き領域が250MB以上ある場合は、回復パーティションのサイズを拡張することなく終了します。また、拡張する必要があっても、回復パーティションを拡張するのに必要な空き領域250MBがOSパーティションにない場合も終了します。
次に、回復パーティションがOS(Windows)パーティションのすぐ後ろにあることを確認し、そうである場合は、WinREを無効化して、C:ドライブ(C:¥Windows¥System32¥Recovery¥winre.wim)に退避されたことを確認して、さらに回復パーティションに残っている他のアイテムをバックアップフォルダーにコピーします。OSパーティションを縮小(Shrink)し、現在の回復パーティションを削除して、OSパーティションの縮小分と以前の回復パーティションの領域を使用して、回復パーティションを作成し直します。
最後に、WinREを再び有効化してスクリプトは終了します。バックアップフォルダーにコピーされたものは自動的には戻りません。各自確認して戻す必要があれば、ユーザー自身が回復パーティションにドライブ文字を割り当ててコピーする必要があります。
サンプルスクリプトは、BIOS/MBRベースのシステムとUEFI/GPTベースのシステムの両方に対応しているなど(注:このブログではUEFI/GPTベースの話に絞っています)、細かな配慮が行き届いているように思えます。しかし、250MBの空き領域になるように拡張するのではなく、空き領域の情報をせっかく取得しているのに、単純に250MB拡張(新たな空き領域は以前の空き領域+250MB)している点が少し残念です。また、250MBという拡張サイズは、以前にも指摘したように、以下のドキュメントで示されている、将来のWinREの更新を見据えた、“現在”推奨される空き容量要件です。今回のWinREの更新(セキュリティ更新プログラム、累積更新プログラム、スクリプトによるオフラインパッチ)には十分過ぎる空き領域です。
UEFI/GPT ベースのハード ドライブ パーティション|パーティションの要件
https://learn.microsoft.com/ja-jp/windows-hardware/manufacture/desktop/configure-uefigpt-based-hard-drive-partitions#partition-requirements
続いて、Windows Server 2019をクリーンインストールした環境で「Resize_Script.ps1」を実行してみました。
Windows Server 2019をクリーンインストールした環境では、回復パーティションはディスクの先頭に配置されています。「Resize_Script.ps1」は回復パーティションがOSの後ろに位置していないことを認識し、“WinRE partition is not after OS partition, cannot perform extension/Need to create a new WinRE partiton after OS partition”と出力します。
「Y」で答えてスクリプトの実行を続行すると、OSパーティションのサイズを現在の回復パーティションのサイズ+250MB(749MB)だけ縮小しますが、最終的に以前と同じ場所であるパーティション1でWinREが再び有効にななるため、何も変わっていないように見えるかもしれません(画面3)。しかし、DISKPARTコマンドを実行してパーティションを確認すると、749MBの回復パーティションは期待通りにディスクの最後尾にあり、そのサイズが749MBであることが分かります。また、「ディスクの管理」スナップインの表示を最新にリフレッシュすれば、以前の回復パーティションの領域が「未割り当て」になっていることを確認できるはずです。
パーティション番号が1なのが気になるかもしれませんが、OSを再起動すればそのパーティション番号は4になります。パーティションを操作した再起動前のセッションでは、回復パーティション(パーティション1)が削除されますが、削除したからといって、パーティション2~4の番号が変更になることはありません。新しい回復パーティション用のプライマリパーティションを作成すると、未使用の番号1が割り当てられます。違和感を持つのはそのためです。OSを再起動すれば、パーティション番号はディスクの前方からの順番通りになります。
画面3 パーティション番号1にあったWinREが、スクリプトの実行で再びパーティション番号1にセットアップされ、サイズや位置が変わったように見えない
画面4 DISKPARTコマンドで確認すると、ディスク最後尾にパーティション番号1が割り当てられているのがわかる。「ディスクの管理」スナップインも表示を更新すれば正しい表示に
このサンプルスクリプトの実行結果として、ディスクの先頭にできてしまう未割り当て領域がどうしても気になるという人がいたら、このブログのvol.4やvol.5・6をご覧ください。
Microsoft提供のサンプルスクリプト「Resize_Script.ps1」には留意点があります。1つは、.NETベースのPowerShell(pwsh.exe)では必ずエラーで失敗することです。その理由については今回は詳しく説明しませんが、「Split()」メソッドの使い方に問題があります。詳しくは、旧ブログ(リンク先は予告なく削除される場合があります)で説明しています。
「Split()」メソッドの使い方の問題は、「-Split」オペレーター(演算子)に書き換えることで回避することができますが、それを回避してもPowerShell(pwsh.exe)で実行するとエラーが発生し、中途半端な状態(OSパーティションが縮小された状態で終了)になることがあります。その原因は、前回の「PatchWinREScript_General.ps1」と同様で、何年も前に非推奨(※1)になっているGet-WmiObjectコマンドレットが使用されており、WindowsのバージョンとPowerShellの組み合わせによってはエラーになる場合があります。
※1 WMICコマンドやGet-WmiObjectコマンドレットの使用は現在は非推奨であり、代わりにGet-CimInstanceなど、CimCmdlets(外部サイト)の使用が推奨されています)。
Windows PowerShell(powershell.exe)の最新バージョンは5.1であり、Microsoftは新機能を含め、Windows PowerShellを更新しないことを発表しています(※2)。現在、新機能の追加や変更は.NETベースのPowerShell(pwsh.exe)に対して行われています。クラウド、オンプレミスのクロスプラットフォーム環境、ハイブリッド環境向けには、新しいPowerShellのほうが向いていますし、パフォーマンスや機能も優れています。しかし、Windowsの管理に関しては互換性を考慮してもWindows PowerShellを使用したほうが無難でしょう。Microsoftの中の人の一部は、レガシなGet-WmiObjectがとてもお好きなようですし、新しいPowerShellで実行されることなんて想定していないようです。なので、サンプル利用時にはお気をつけてください。
※2 Windows PowerShell とは(外部サイト)、Windows PowerShell 5.1 と PowerShell 7.x の相違点(外部サイト)
「PatchWinREScript_General.ps1」のときと同じように、まずは「Resize_script.ps1」を本来の目的(回復パーティションのサイズ拡張)のために試してみました。次回は、このスクリプトから何が頂戴できるのか、お楽しみに。