私が所持している複数のWindows 10 パソコンで同じエラーが発生しました。
まず結論から書くと、大半のパソコンにはインストールする必要のない更新プログラムです。
2024年3月現在、この更新プログラムをどうしてもインストールしたい場合、いくつかの手法で対応できますが、
ある程度パソコンの知識とスキルが必要な対応となります。
- どのような目的の更新プログラムか?
- エラーが発生した原因は?
- 現時点の対応方法は?
など調べて検証した事をまとめました。
更新プログラム「KB5034441」の公式記事にて特定の条件に合致する環境では更新プログラムの適用は不要と自動的に判断し、更新プログラムの提供を終了したとのこと。
これより大半の環境でエラーが解消するはずです。詳しくはこちらの記事をご確認ください。
以降の内容はこのエラーが発生した当時の対応方法を記載しています。Windows 11 へのアップグレードなど一部内容は今後も参考になるかと思われます。
必要に応じて対応をご検討ください。
- Windows 10 ユーザーの方
(Windows 11では発生しません)
- 更新プログラム「KB5034441」でエラー“0x80070643”が発生した方
- 更新プログラムの情報やエラーの原因、対応方法を知りたい方
事象
2024年1月、Windows 10 Pro で Windows Updateを実施するも、エラーが発生しました。
詳しく内容を確認すると、更新プログラム「KB5034441」でエラー“0x80070643”というエラー発生していることを確認。
エラー発生した直後の対応は、もう一度更新してみたり、システムドライブをクリーンナップしてからリトライしたり、トラブルシューティングを実施してからリトライなどを試しましたが、いずれの方法も解決できませんでした。
(詳細な対応方法は後述しています。)
調査内容
更新プログラム「KB5034441」とは
実行中の PC 上の Windows 回復環境 (WinRE) に Safe OS 動的更新 (KB5034232) を自動的に適用し、攻撃者がWinREを使用してBitLocker暗号化をバイパスできる可能性があるセキュリティの脆弱性に対処します。詳細については、CVE-2024-20666 を参照してください。
引用元:KB5034441: Windows Recovery Environment update for Windows 10, version 21H2 and 22H2: January 9, 2024
つまりは、WinRE(回復パーティション)のセキュリティ強化のため、更新プログラム「 KB5034232 」を導入する事を目的とした更新プログラムということです。
KB5034441で修正するセキュリティの脆弱性「CVE-2024-20666」とは
こちらの公式文書を確認し要約してみると、
Windows OSのBitLocker機能でハードディスクのセキュリティを強化している場合、 WinREの脆弱性をつき、BitLockerの保護機能をすり抜けて攻撃される可能性がある問題。
ということがわかりました。
“KB5034441”を適用するべき環境
今回エラーになった更新プログラムは「 Windows 10用に提供 」されています。
また、更新プログラムの中身は「 BitLocker(ビットロッカー) 」というWindows 標準機能 でディスクの暗号化機能をオンにしている環境(デフォルトはオフ)のみ関わる内容。
なお、BitLockerがオンの環境で問題が発生しうるということですが、更新プログラム自体は、BitLockerがオフの環境にも配布される更新プログラムです。
(現時点、設定がオフでも将来的にオンとする可能性があるため、配布していると思われる。)
以上のことをふまえると、「 下記の条件に該当する環境のみ、この更新プログラムを適用する必要がある 」と言えます。
- 条件1:対象のWindows バージョンであること
このバージョンのWindows環境のみ、更新プログラムが配布されています。- Windows 10 Version 22H2
- Windows 10 Version 21H2
- 条件2:Windows 10 でBitLockerを有効化できるエディションであること
下記にWindows 10 のエディション毎、BitLockerを設定できるか有無を記載。
:Windows 10 Home
:Windows 10 Sモード
:Windows 10 Pro
:Windows 10 Enterprise
:Windows 10 Education
:Windows 10 Pro Education/SE
参考情報:Windows 10 の エディション – Wikipedia
参考情報:BitLockerの対象エディションと有効化可能なライセンスについて
- 条件3:現在、BitLockerを有効にしていること、または今後有効にする予定があること
前述した通り、Windows 10 において BitLocker機能は規定でオフとなっているので、
条件3に該当する環境はかなり少ないのではないでしょうか。
逆にこの更新プログラムを適用しなくても良い環境は、 BitLocker機能を使用していない、もしくは使用する予定がない 環境です。
この環境の場合、更新プログラム「 KB5034441 」がエラーとなりインストールできなくてもセキュリティーリスクが発生しないということになります。
環境の条件を確認する方法
上記の条件で記載した Windows のバージョン と エディション の確認方法 と BitLockerの設定状態を確認する方法 を紹介します。
ヒント:開閉できるエリア
下記のようなエリアはクリックすると開閉可能っピ 👍
Windows の バージョン と エディション を確認する方法
画面で確認する方法(GUI)
ms-settings:about
」で設定画面、システムの詳細情報が開くms-settings:about
詳細情報のページが開くので、中腹ぐらいまでスクロールし、
項目「 Windows の仕様 」に記載されている“エディション” と “バージョン” を確認。
補足情報:コマンドで確認したい方はコチラ
コマンドで確認する方法(CLI – PowerShellコマンドレット)
powershell
」と入力PS C:\WINDOWS\system32> Get-WindowsEdition -Online
Edition : Professional
PS C:\WINDOWS\system32>
PS C:\WINDOWS\system32> Get-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion" | Select-Object DisplayVersion
DisplayVersion
--------------
22H2
PS C:\WINDOWS\system32>
BitLockerの設定を確認する方法
画面で確認する方法(GUI – マウス操作編)
※ コントロールパネルの表示方法:カテゴリの場合
ひとつでもBitLockerが有効となっている場合、この更新プログラムの適用が必要です。
補足情報:その他のGUI確認方法 や コマンドで確認したい方はコチラ
画面で確認する方法(GUI – “ファイル名を指定して実行”を使用)
control /name Microsoft.BitLockerDriveEncryption
」と入力しEnterキーを押すひとつでもBitLockerが有効となっている場合、この更新プログラムの適用が必要です。
コマンドで確認する方法(CLI – PowerShellコマンドレット)
powershell
」と入力Get-BitLockerVolume
」を実行下記、実際に実行した結果を例に説明すると、項目「 ProtectionStatus
」の状態で確認できます。
- 結果が On であれば、BitLockerが有効な状態
- 結果が Off であれば、BitLockerが無効の状態
PS C:\WINDOWS\system32> Get-BitLockerVolume
ComputerName: "コンピューター名"
VolumeType Mount CapacityGB VolumeStatus Encryption KeyProtector AutoUnlock Protecti
Point Percentage Enabled onStatus
---------- ----- ---------- ------------ ---------- ------------ ---------- --------
Data G: 465.76 FullyDecrypted 0 {} Off
OperatingSystem C: 130.34 FullyDecrypted 0 {} Off
Data D: 106.35 FullyDecrypted 0 {} Off
PS C:\WINDOWS\system32>
原因
冒頭で説明している更新プログラムの公式文書には、下記のような記述が追記されました。
(私が最初にこのエラーを確認した2024年1月時点、エラーに関する記載はなかったと記憶しています。
おそらく、エラーの報告が数多くあがり対応されたのでしょう。)
重要
このアップデートを正常にインストールするには、回復パーティションに 250 MB の空き領域が必要です。回復パーティションに十分な空き領域がない場合、この更新は失敗します。この場合、次のエラー メッセージが表示されます。
0x80070643 – ERROR_INSTALL_FAILURE
このエラーを回避するか、この障害から回復するには、 手順に従ってパーティションのサイズを手動で変更し、WinRE 更新プログラムをインストールして から、この更新プログラムのインストールを試してください。
または、サンプル スクリプトを使用して WinRE 回復パーティションのサイズを増やすには、「 Windows RE パーティションの拡張 」を参照してください。
引用元:KB5034441: Windows Recovery Environment update for Windows 10, version 21H2 and 22H2: January 9, 2024
エラーの原因は、「 回復パーティションの空き領域が 250 MB 以上ない環境で発生 」との事。
私はWindows 10 OSの環境を複数台、所持しています。それらほぼ全ての環境において、回復パーティションの空き領域が 250 MB よりも小さく条件と合致し、今回のWindows Updateのエラーも発生しました。
ただ、限られた少数の環境ではありますが、回復パーティションの空き領域が 250 MB 以上の環境でも、
エラーが発生しました。
(回復パーティションの空き領域は、約500 MB でした。)
この例外的な環境の対応では、Windows 11 にアップグレードしたことで問題が解決しています。
(詳しい対応方法は後述)
参考情報:Windows における パーティションの概要
上記の公式文書をみると、回復パーティションの総容量は通常、500 ~ 700 MB とのこと。
エラーが発生した環境は、ほぼディスクの総容量が少ない仮想環境で発生していました。
おそらくWindows OS がインストールされている ディスクの総容量が少なく、
それに比例し回復パーティションも自動的に小さく設定されているのでしょう。
今回のエラーは リソースを必要最低限、小さく設定しているであろう仮想環境で発生しやすいエラー という事が言えます。
対応方法
2024年3月現在、おおきくわけて3つの対応方法があります。
いずれかの方法を対応することでエラーを消すことができます。
こちらで3つの対応方法を紹介していますが、それぞれ別の環境を使って検証し、このエラーが解消できました。
ご自身にとって、どの対応方法が適切か検討した上でご対応ください。
私が個人的にオススメしているのは対応1 の 「エラーが発生している更新プログラムを一時的に非表示にする方法」です。
- 対応1.エラーが発生している更新プログラムを一時的に非表示にする方法
私のWindows 10 環境だけでも、かなりの環境でエラーが発生しました。
世界的にみても、最新の Windows 11 よりも Windows 10 の方がシェア率が高く(調査:statcounter調べ)、
ネットで検索してもエラーが発生した事例がかなり多いようです。
2024年3月現在で公式が公開している対応方法は、1つがコマンドプロンプトを使った対応方法で、
もう1つがPowerShellスクリプトを作成し実行する対応方法です。
これらの対応方法は、ある程度パソコンの知識とスキルが必要な作業となり、一般のユーザーは対応できません。
一部のユーザーのみが対応できる方法となる為、位置づけとしては暫定的な対応の分類だと思われます。
また、繰り返しになりますが、BitLockerを有効にしていなければ問題のない脆弱性の問題。
更新プログラムの差し替えなど、Microsoftの正式な対応方法を待つのが得策です。
対応方法として、エラーが発生している更新プログラムを一時的に非表示にする方法を後述します。
- 対応2.回復パーティションを拡張して更新プログラムを導入する方法
この方法は、公式から周知されている方法 や ネットで出回っている方法 など、この中でもいくつか手法があります。
対応2-1 手動でパーティションの拡張を行う方法(Microsoft公式の手順その1)
対応2-2 PowerShellスクリプトでパーティションを拡張する方法(Microsoft公式の手順その2)
対応2-3 WinREを再構成する方法
私が実際に試して有効だった2つの方法を後述。
- 対応3.Windows 11 にアップグレードする方法
“Windows 10 に該当する問題なのであれば、Windows 11 にアップグレードしちゃえばいいじゃない。”という思考でこの方法を試しました。
私の環境ではうまくいきましたが、すべての環境でうまくいくかはわかりません。
そもそもシステム要件的にアップグレードできないという環境もありますね。
また、アップグレードは、リスクの高い作業となるため、必要に応じてシステムバックアップを取得するなど、
万全を期して対応することをオススメします。
私の環境で問題なくアップグレードできた際の手順を後述します。
対応1.エラーが発生している更新プログラムを一時的に非表示にする方法
この手順により、Microsoft の正式な対応方法が提示されるまでエラー表示を消すことができます。
BitLockerを有効にしなければ、非表示のままで問題ないですが、
作業後、この更新プログラムを非表示にしたことを忘れないようにメモしておきましょう。
この更新プログラムを非表示にする方法は、別記事として作成中となります。
作成後、こちらにリンクを貼ろうと思います。
2024年3月29日 記事の作成が完了。下記の記事をご参照ください。
補足情報:上記で紹介している記事を参考に更新プログラムを非表示してみた。
作業手順のポイントになる部分を抜粋して紹介。
対応2.回復パーティションを拡張して更新プログラムを導入する方法
この中でもいくつかの方法があります。私が試した内容は下記の3点です。
- 対応2-1.手動でパーティションの拡張を行う方法(Microsoft公式の手順その1)
こちらの記事で方法を公開中。
👍 公式からの手順ということもあり、個人的にはこの方法が一番オススメ。
対応2-2.PowerShellスクリプトでパーティションを拡張する方法(Microsoft公式の手順その2)
こちらの記事で方法を公開中。
ここで紹介されているPowerShellスクリプトは、実行するための制約が多すぎて使い物になりませんでした。
👎 オススメできない対応方法です。
- 対応2-3.WinREを再構成する方法
こちらの記事で方法を公開中。
この更新プログラムに対するMicrosoft公式の方法ではありませんが、対応可能な方法でした。
また、この記事は更新プログラムが配信されて初期にやりとりされていたMicrosoft Comminutyでの情報を参考にされていると思われます。
このうち、実績のある「 対応2-1の手動でパーティションの拡張を行う方法 」と 「 対応2-3のWinREを再構成する方法 」を紹介。
ヒント:開閉できるエリア
下記のようなエリアはクリックすると開閉可能っピ 👍
対応2-1.手動でパーティションの拡張を行う方法
下記、公式の記事で紹介している内容をココでより詳しく手順を解説していきます。
ファイル名を指定して実行で「cmd」と入力。つづいて「 Ctrl + Shift + Enterキー 」でコマンドプロンプトを管理者権限で実行する。
- 公式でもコマンドプロンプトを起動していますが、この手順をPowerShellに置き換えて実行しても問題ありません。
Windows REの状態が「 Enabled 」となり起動中であることを確認する。
reagentc /info
C:\WINDOWS\system32>reagentc /info
Windows 回復環境 (Windows RE) およびシステム リセット構成
情報:
Windows RE の状態: Enabled
Windows RE の場所: \\?\GLOBALROOT\device\harddisk1\partition5\Recovery\WindowsRE
ブート構成データ (BCD) ID: 3604668f-249b-11eb-a108-999157d203d8
回復イメージの場所:
回復イメージ インデックス: 0
カスタム イメージの場所:
カスタム イメージ インデックス: 0
REAGENTC.EXE: 操作は成功しました。
C:\WINDOWS\system32>
reagentc /disable
C:\WINDOWS\system32>reagentc /disable
REAGENTC.EXE: 操作は成功しました。
C:\WINDOWS\system32>
reagentc /info
C:\WINDOWS\system32>reagentc /info
Windows 回復環境 (Windows RE) およびシステム リセット構成
情報:
Windows RE の状態: Disabled
Windows RE の場所:
ブート構成データ (BCD) ID: 00000000-0000-0000-0000-000000000000
回復イメージの場所:
回復イメージ インデックス: 0
カスタム イメージの場所:
カスタム イメージ インデックス: 0
REAGENTC.EXE: 操作は成功しました。
C:\WINDOWS\system32>
diskpart
C:\WINDOWS\system32>diskpart
Microsoft DiskPart バージョン 10.0.19041.3636
Copyright (C) Microsoft Corporation.
コンピューター: "コンピューター名"
DISKPART>
list disk
DISKPART> list disk
ディスク 状態 サイズ 空き ダイナ GPT
### ミック
------------ ------------- ------- ------- --- ---
ディスク 0 オンライン 465 GB 1024 KB
ディスク 1 オンライン 238 GB 12 MB *
DISKPART>
私の環境では、ディスクが2枚あります。
sel disk 1
DISKPART> sel disk 1
ディスク 1 が選択されました。
DISKPART>
私の環境では、「 ディスク1 」にWindows OSがインストールされています。
どのディスクにインストールされているか不明な方は、いずれかのディスクを選択した後、
「 list part
」コマンドで、Cドライブ(規定の場合)があるか確認してください。
これらコマンドは、ただディスクを選択(sel
= select)しているか。一覧表示(list
)で中身を確認しているだけなので、
臆することなくコマンドを実行してみてください。
また、冒頭に実行した「 reagentc /info
」の結果でも、Windows OSがインストールされているドライブを判断できます。
私の環境の場合、「 Windows RE の場所: \?\GLOBALROOT\device\harddisk1\partition5\Recovery\WindowsRE
」となっていた為、「 ディスクの1番 の パーティション5番 」に回復パーティションが存在します。
回復パーティションと同じディスクにCドライブがあるので、システムドライブがインストールされているディスクは「 1 」だと判断できます。
list part
DISKPART> list part
Partition ### Type Size Offset
------------- ------------------ ------- -------
Partition 1 システム 700 MB 1024 KB
Partition 2 予約 128 MB 701 MB
Partition 3 プライマリ 130 GB 829 MB
Partition 4 プライマリ 105 GB 131 GB
Partition 5 回復 990 MB 236 GB
Partition 6 回復 1086 MB 237 GB
DISKPART>
以後の作業では、システムドライブを選択するので、直接的に関係のない補足情報ですが、
わたしの環境では、Partition 5 と Partition 6 で2つ回復パーティションがあります。
これは、以前にWindows OS を Windows 7 から Windows 10 にアップグレードした為、
このようなパーティション構成になっています。
前述しているとおり、「reagentc /info
」の結果により現在使用中の回復パーティションを確認可能です。
私の環境では、Partition 5 が Windows 10 で使用中の回復パーティション。
Partition 6 にある回復パーティションは、Windows 7 で使用していた回復パーティションです。
sel part 4
DISKPART> sel part 4
パーティション 4 が選択されました。
DISKPART>
shrink desired=250 minimum=250
DISKPART> shrink desired=250 minimum=250
ボリュームは、次の方法で正常に縮小されました: 250 MB
DISKPART>
パソコンの知識に明るい方であれば、システムドライブでなくてもよいです。総容量に余裕のあるパーティションを選択しなおして縮小してください。
同じ環境でずっとWindows アップグレードを実施してる場合、複数回復パーティションがある場合があります。
冒頭に実行した「 reagentc /info
」の結果により、現在どの回復パーティションを使用しているか確認できます。
私の環境の場合、「 Windows RE の場所: \?\GLOBALROOT\device\harddisk1\partition5\Recovery\WindowsRE
」となっていた為、「 ディスクの1番 の パーティション5番 」に回復パーティションが存在します。
sel part 5
DISKPART> sel part 5
パーティション 5 が選択されました。
DISKPART>
delete partition override
DISKPART> delete partition override
DiskPart は選択されたパーティションを正常に削除しました。
DISKPART>
list disk
DISKPART> list disk
ディスク 状態 サイズ 空き ダイナ GPT
### ミック
------------ ------------- ------- ------- --- ---
ディスク 0 オンライン 465 GB 1024 KB
* ディスク 1 オンライン 238 GB 1252 MB *
DISKPART>
システムドライブが入っているディスク1のGPT欄に「 *
」の印がある場合、GPT パーティションである事を確認。
なお、このGPT欄に「 *
」の印がない場合は、MPTパーティションとなる。
ここでの確認結果により、STEP14 の GPTパーティションの手順 か STEP15 の MPTパーティションの手順 か作業が分岐します。
STEP 13 で システムドライブがあるディスク番号の行のGPT項目に「 * 」がある場合のみ、本項を対応。
STEP 15 の MPT パーティションだった場合の手順は対応不要。
create partition primary id=de94bba4-06d1-4d40-a16a-bfd50179d6ac
DISKPART> create partition primary id=de94bba4-06d1-4d40-a16a-bfd50179d6ac
DiskPart は指定したパーティションの作成に成功しました。
DISKPART>
gpt attributes =0x8000000000000001
DISKPART> gpt attributes =0x8000000000000001
選択された GPT パーティションに DiskPart で属性を割り当てました。
DISKPART>
次のSTEP15は、MPT パーティションのため、手順を飛ばす。
STEP 13 で システムドライブがあるディスク番号の行のGPT項目に「 * 」がなく空欄だった場合のみ、本項を対応。
STEP 14 の GPT パーティションだった場合の手順は対応不要。
create partition primary id=27
※ MPT パーティション環境は未検証のため、実際に実行したコマンド結果なし。
format quick fs=ntfs label="Windows RE tools"
DISKPART> format quick fs=ntfs label="Windows RE tools"
100% 完了しました
DiskPart は、ボリュームのフォーマットを完了しました。
DISKPART>
list vol
DISKPART> list vol
Volume ### Ltr Label Fs Type Size Status Info
---------- --- ----------- ---- ---------- ------- --------- --------
Volume 0 G ボリューム NTFS Partition 465 GB 正常
Volume 1 C OS NTFS Partition 130 GB 正常 ブート
Volume 2 D ボリューム NTFS Partition 105 GB 正常
Volume 3 ESP FAT32 Partition 700 MB 正常 システム
Volume 5 DELLSUPPORT NTFS Partition 1086 MB 正常 非表示
* Volume 6 Windows RE NTFS Partition 1240 MB 正常 非表示
DISKPART>
exit
DISKPART> exit
DiskPart を終了しています...
C:\\WINDOWS\\system32>
reagentc /enable
C:\\WINDOWS\\system32>reagentc /enable
REAGENTC.EXE: 操作は成功しました。
C:\\WINDOWS\\system32>
reagentc /info
C:\\WINDOWS\\system32>reagentc /info
Windows 回復環境 (Windows RE) およびシステム リセット構成
情報:
Windows RE の状態: Enabled
Windows RE の場所: \\\\?\\GLOBALROOT\\device\\harddisk1\\partition5\\Recovery\\WindowsRE
ブート構成データ (BCD) ID: 36046691-249b-11eb-a108-999157d203d8
回復イメージの場所:
回復イメージ インデックス: 0
カスタム イメージの場所:
カスタム イメージ インデックス: 0
REAGENTC.EXE: 操作は成功しました。
C:\\WINDOWS\\system32>
対応2-3.WinREを再構成する方法
こちらの公式サイトに掲載されているPowerShellのコードより、PowerShellスクリプトファイル(*.ps1)を作成。
なお、保存する際の文字コードは「 UTF-8 」を設定してください。
公式で推奨されているのは、バージョン 2004 以降 の「PatchWinREScript_2004plus.ps1」です。
公式の記事で記載しているとおり、本件のエラーが発生しているKB5034441以外の更新プログラムは全てインストールした後に、
推奨されている「PatchWinREScript_2004plus.ps1」を準備したほうが問題が発生しにくいと思われます。
Windows 10 バージョン 2004 以降:PatchWinREScript_2004plus.ps1
2024年3月現在のコードをコピペ。
空行は正規表現により削除しました。また、インデントも合わせています。
################################################################################################
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
################################################################################################
Param (
[Parameter(HelpMessage="Work Directory for patch WinRE")][string]$workDir="",
[Parameter(Mandatory=$true,HelpMessage="Path of target package")][string]$packagePath
)
# ------------------------------------
# Help functions
# ------------------------------------
# Log message
function LogMessage([string]$message)
{
$message = "$([DateTime]::Now) - $message"
Write-Host $message
}
function IsTPMBasedProtector
{
$DriveLetter = $env:SystemDrive
LogMessage("Checking BitLocker status")
$BitLocker = Get-WmiObject -Namespace "Root\cimv2\Security\MicrosoftVolumeEncryption" -Class "Win32_EncryptableVolume" -Filter "DriveLetter = '$DriveLetter'"
if(-not $BitLocker)
{
LogMessage("No BitLocker object")
return $False
}
$protectionEnabled = $False
switch ($BitLocker.GetProtectionStatus().protectionStatus){
("0"){
LogMessage("Unprotected")
break
}
("1"){
LogMessage("Protected")
$protectionEnabled = $True
break
}
("2"){
LogMessage("Uknown")
break
}
default{
LogMessage("NoReturn")
break
}
}
if (!$protectionEnabled)
{
LogMessage("Bitlocker isn’t enabled on the OS")
return $False
}
$ProtectorIds = $BitLocker.GetKeyProtectors("0").volumekeyprotectorID
$return = $False
foreach ($ProtectorID in $ProtectorIds){
$KeyProtectorType = $BitLocker.GetKeyProtectorType($ProtectorID).KeyProtectorType
switch($KeyProtectorType){
"1"{
LogMessage("Trusted Platform Module (TPM)")
$return = $True
break
}
"4"{
LogMessage("TPM And PIN")
$return = $True
break
}
"5"{
LogMessage("TPM And Startup Key")
$return = $True
break
}
"6"{
LogMessage("TPM And PIN And Startup Key")
$return = $True
break
}
default {break}
}#endSwitch
}#EndForeach
if ($return)
{
LogMessage("Has TPM-based protector")
}
else
{
LogMessage("Doesn't have TPM-based protector")
}
return $return
}
function SetRegistrykeyForSuccess
{
reg add HKLM\SOFTWARE\Microsoft\PushButtonReset /v WinREPathScriptSucceed_CVE_2024_20666 /d 1 /f
}
function TargetfileVersionExam([string]$mountDir)
{
# Exam target binary
$targetBinary=$mountDir + "\Windows\System32\winload.efi"
LogMessage("TargetFile: " + $targetBinary)
$realNTVersion = [Diagnostics.FileVersionInfo]::GetVersionInfo($targetBinary).ProductVersion
$versionString = "$($realNTVersion.Split('.')[0]).$($realNTVersion.Split('.')[1])"
$fileVersion = $($realNTVersion.Split('.')[2])
$fileRevision = $($realNTVersion.Split('.')[3])
LogMessage("Target file version: " + $realNTVersion)
if (!($versionString -eq "10.0"))
{
LogMessage("Not Windows 10 or later")
return $False
}
$hasUpdated = $False
#Windows 10, version 1507 10240.20400
#Windows 10, version 1607 14393.6610
#Windows 10, version 1809 17763.5322
#Windows 10, version 2004 1904X.3920
#Windows 11, version 21H2 22000.2710
#Windows 11, version 22H2 22621.3000
switch ($fileVersion) {
"10240" {
LogMessage("Windows 10, version 1507")
if ($fileRevision -ge 20400)
{
LogMessage("Windows 10, version 1507 with revision " + $fileRevision + " >= 20400, updates have been applied")
$hasUpdated = $True
}
break
}
"14393" {
LogMessage("Windows 10, version 1607")
if ($fileRevision -ge 6610)
{
LogMessage("Windows 10, version 1607 with revision " + $fileRevision + " >= 6610, updates have been applied")
$hasUpdated = $True
}
break
}
"17763" {
LogMessage("Windows 10, version 1809")
if ($fileRevision -ge 5322)
{
LogMessage("Windows 10, version 1809 with revision " + $fileRevision + " >= 5322, updates have been applied")
$hasUpdated = $True
}
break
}
"19041" {
LogMessage("Windows 10, version 2004")
if ($fileRevision -ge 3920)
{
LogMessage("Windows 10, version 2004 with revision " + $fileRevision + " >= 3920, updates have been applied")
$hasUpdated = $True
}
break
}
"22000" {
LogMessage("Windows 11, version 21H2")
if ($fileRevision -ge 2710)
{
LogMessage("Windows 11, version 21H2 with revision " + $fileRevision + " >= 2710, updates have been applied")
$hasUpdated = $True
}
break
}
"22621" {
LogMessage("Windows 11, version 22H2")
if ($fileRevision -ge 3000)
{
LogMessage("Windows 11, version 22H2 with revision " + $fileRevision + " >= 3000, updates have been applied")
$hasUpdated = $True
}
break
}
default {
LogMessage("Warning: unsupported OS version")
}
}
return $hasUpdated
}
function PatchPackage([string]$mountDir, [string]$packagePath)
{
# Exam target binary
$hasUpdated =TargetfileVersionExam($mountDir)
if ($hasUpdated)
{
LogMessage("The update has already been added to WinRE")
SetRegistrykeyForSuccess
return $False
}
# Add package
LogMessage("Apply package:" + $packagePath)
Dism /Add-Package /Image:$mountDir /PackagePath:$packagePath
if ($LASTEXITCODE -eq 0)
{
LogMessage("Successfully applied the package")
}
else
{
LogMessage("Applying the package failed with exit code: " + $LASTEXITCODE)
return $False
}
# Cleanup recovery image
LogMessage("Cleanup image")
Dism /image:$mountDir /cleanup-image /StartComponentCleanup /ResetBase
if ($LASTEXITCODE -eq 0)
{
LogMessage("Cleanup image succeed")
}
else
{
LogMessage("Cleanup image failed: " + $LASTEXITCODE)
return $False
}
return $True
}
# ------------------------------------
# Execution starts
# ------------------------------------
# Check breadcrumb
if (Test-Path HKLM:\Software\Microsoft\PushButtonReset)
{
$values = Get-ItemProperty -Path HKLM:\Software\Microsoft\PushButtonReset
if (!(-not $values))
{
if (Get-Member -InputObject $values -Name WinREPathScriptSucceed_CVE_2024_20666)
{
$value = Get-ItemProperty -Path HKLM:\Software\Microsoft\PushButtonReset -Name WinREPathScriptSucceed_CVE_2024_20666
if ($value.WinREPathScriptSucceed_CVE_2024_20666 -eq 1)
{
LogMessage("This script was previously run successfully")
exit 1
}
}
}
}
if ([string]::IsNullorEmpty($workDir))
{
LogMessage("No input for mount directory")
LogMessage("Use default path from temporary directory")
$workDir = [System.IO.Path]::GetTempPath()
}
LogMessage("Working Dir: " + $workDir)
$name = "9f8131ee-878f-4525-bf31-e446aac3016a_Mount"
$mountDir = Join-Path $workDir $name
LogMessage("MountDir: " + $mountdir)
# Delete existing mount directory
if (Test-Path $mountDir)
{
LogMessage("Mount directory: " + $mountDir + " already exists")
LogMessage("Try to unmount it")
Dism /unmount-image /mountDir:$mountDir /discard
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Warning: unmount failed: " + $LASTEXITCODE)
}
LogMessage("Delete existing mount direcotry " + $mountDir)
Remove-Item $mountDir -Recurse
}
# Create mount directory
LogMessage("Create mount directory " + $mountDir)
New-Item -Path $mountDir -ItemType Directory
# Set ACL for mount directory
LogMessage("Set ACL for mount directory")
icacls $mountDir /inheritance:r
icacls $mountDir /grant:r SYSTEM:"(OI)(CI)(F)"
icacls $mountDir /grant:r *S-1-5-32-544:"(OI)(CI)(F)"
# Mount WinRE
LogMessage("Mount WinRE:")
reagentc /mountre /path $mountdir
if ($LASTEXITCODE -eq 0)
{
# Patch WinRE
if (PatchPackage -mountDir $mountDir -packagePath $packagePath)
{
$hasUpdated = TargetfileVersionExam($mountDir)
if ($hasUpdated)
{
LogMessage("After patch, find expected version for target file")
}
else
{
LogMessage("Warning: After applying the patch, unexpected version found for the target file")
}
LogMessage("Patch succeed, unmount to commit change")
Dism /unmount-image /mountDir:$mountDir /commit
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Unmount failed: " + $LASTEXITCODE)
exit 1
}
else
{
if ($hasUpdated)
{
if (IsTPMBasedProtector)
{
# Disable WinRE and re-enable it to let new WinRE be trusted by BitLocker
LogMessage("Disable WinRE")
reagentc /disable
LogMessage("Re-enable WinRE")
reagentc /enable
reagentc /info
}
# Leave a breadcrumb indicates the script has succeed
SetRegistrykeyForSuccess
}
}
}
else
{
LogMessage("Patch failed or is not applicable, discard unmount")
Dism /unmount-image /mountDir:$mountDir /discard
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Unmount failed: " + $LASTEXITCODE)
exit 1
}
}
}
else
{
LogMessage("Mount failed: " + $LASTEXITCODE)
}
# Cleanup Mount directory in the end
LogMessage("Delete mount direcotry")
Remove-Item $mountDir -Recurse
Windows 10 バージョン 1909 以前:PatchWinREScript_General.ps1
2024年3月現在のコードよりコピペ。
空行は正規表現により削除しました。また、インデントも合わせています。
################################################################################################
#
# Copyright (c) Microsoft Corporation.
# Licensed under the MIT License.
#
# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.
#
################################################################################################
Param (
[Parameter(HelpMessage="Work Directory for patch WinRE")][string]$workDir="",
[Parameter(Mandatory=$true,HelpMessage="Path of target package")][string]$packagePath
)
# ------------------------------------
# Help functions
# ------------------------------------
# Log message
function LogMessage([string]$message)
{
$message = "$([DateTime]::Now) - $message"
Write-Host $message
}
function IsTPMBasedProtector
{
$DriveLetter = $env:SystemDrive
LogMessage("Checking BitLocker status")
$BitLocker = Get-WmiObject -Namespace "Root\cimv2\Security\MicrosoftVolumeEncryption" -Class "Win32_EncryptableVolume" -Filter "DriveLetter = '$DriveLetter'"
if(-not $BitLocker)
{
LogMessage("No BitLocker object")
return $False
}
$protectionEnabled = $False
switch ($BitLocker.GetProtectionStatus().protectionStatus){
("0"){
LogMessage("Unprotected")
break
}
("1"){
LogMessage("Protected")
$protectionEnabled = $True
break
}
("2"){
LogMessage("Uknown")
break
}
default{
LogMessage("NoReturn")
break
}
}
if (!$protectionEnabled)
{
LogMessage("Bitlocker isn’t enabled on the OS")
return $False
}
$ProtectorIds = $BitLocker.GetKeyProtectors("0").volumekeyprotectorID
$return = $False
foreach ($ProtectorID in $ProtectorIds){
$KeyProtectorType = $BitLocker.GetKeyProtectorType($ProtectorID).KeyProtectorType
switch($KeyProtectorType){
"1"{
LogMessage("Trusted Platform Module (TPM)")
$return = $True
break
}
"4"{
LogMessage("TPM And PIN")
$return = $True
break
}
"5"{
LogMessage("TPM And Startup Key")
$return = $True
break
}
"6"{
LogMessage("TPM And PIN And Startup Key")
$return = $True
break
}
default {break}
}#endSwitch
}#EndForeach
if ($return)
{
LogMessage("Has TPM-based protector")
}
else
{
LogMessage("Doesn't have TPM-based protector")
}
return $return
}
function SetRegistrykeyForSuccess
{
reg add HKLM\SOFTWARE\Microsoft\PushButtonReset /v WinREPathScriptSucceed_CVE_2024_20666 /d 1 /f
}
function TargetfileVersionExam([string]$mountDir)
{
# Exam target binary
$targetBinary=$mountDir + "\Windows\System32\winload.efi"
LogMessage("TargetFile: " + $targetBinary)
$realNTVersion = [Diagnostics.FileVersionInfo]::GetVersionInfo($targetBinary).ProductVersion
$versionString = "$($realNTVersion.Split('.')[0]).$($realNTVersion.Split('.')[1])"
$fileVersion = $($realNTVersion.Split('.')[2])
$fileRevision = $($realNTVersion.Split('.')[3])
LogMessage("Target file version: " + $realNTVersion)
if (!($versionString -eq "10.0"))
{
LogMessage("Not Windows 10 or later")
return $False
}
$hasUpdated = $False
#Windows 10, version 1507 10240.20400
#Windows 10, version 1607 14393.6610
#Windows 10, version 1809 17763.5322
#Windows 10, version 2004 1904X.3920
#Windows 11, version 21H2 22000.2710
#Windows 11, version 22H2 22621.3000
switch ($fileVersion) {
"10240" {
LogMessage("Windows 10, version 1507")
if ($fileRevision -ge 20400)
{
LogMessage("Windows 10, version 1507 with revision " + $fileRevision + " >= 20400, updates have been applied")
$hasUpdated = $True
}
break
}
"14393" {
LogMessage("Windows 10, version 1607")
if ($fileRevision -ge 6610)
{
LogMessage("Windows 10, version 1607 with revision " + $fileRevision + " >= 6610, updates have been applied")
$hasUpdated = $True
}
break
}
"17763" {
LogMessage("Windows 10, version 1809")
if ($fileRevision -ge 5322)
{
LogMessage("Windows 10, version 1809 with revision " + $fileRevision + " >= 5322, updates have been applied")
$hasUpdated = $True
}
break
}
"19041" {
LogMessage("Windows 10, version 2004")
if ($fileRevision -ge 3920)
{
LogMessage("Windows 10, version 2004 with revision " + $fileRevision + " >= 3920, updates have been applied")
$hasUpdated = $True
}
break
}
"22000" {
LogMessage("Windows 11, version 21H2")
if ($fileRevision -ge 2710)
{
LogMessage("Windows 11, version 21H2 with revision " + $fileRevision + " >= 2710, updates have been applied")
$hasUpdated = $True
}
break
}
"22621" {
LogMessage("Windows 11, version 22H2")
if ($fileRevision -ge 3000)
{
LogMessage("Windows 11, version 22H2 with revision " + $fileRevision + " >= 3000, updates have been applied")
$hasUpdated = $True
}
break
}
default {
LogMessage("Warning: unsupported OS version")
}
}
return $hasUpdated
}
function PatchPackage([string]$mountDir, [string]$packagePath)
{
# Exam target binary
$hasUpdated = TargetfileVersionExam($mountDir)
if ($hasUpdated)
{
LogMessage("The update has already been added to WinRE")
SetRegistrykeyForSuccess
return $False
}
# Add package
LogMessage("Apply package:" + $packagePath)
Dism /Add-Package /Image:$mountDir /PackagePath:$packagePath
if ($LASTEXITCODE -eq 0)
{
LogMessage("Successfully applied the package")
}
else
{
LogMessage("Applying the package failed with exit code: " + $LASTEXITCODE)
return $False
}
# Cleanup recovery image
LogMessage("Cleanup image")
Dism /image:$mountDir /cleanup-image /StartComponentCleanup /ResetBase
if ($LASTEXITCODE -eq 0)
{
LogMessage("Cleanup image succeed")
}
else
{
LogMessage("Cleanup image failed: " + $LASTEXITCODE)
return $False
}
return $True
}
# ------------------------------------
# Execution starts
# ------------------------------------
# Check breadcrumb
if (Test-Path HKLM:\Software\Microsoft\PushButtonReset)
{
$values = Get-ItemProperty -Path HKLM:\Software\Microsoft\PushButtonReset
if (!(-not $values))
{
if (Get-Member -InputObject $values -Name WinREPathScriptSucceed_CVE_2024_20666)
{
$value = Get-ItemProperty -Path HKLM:\Software\Microsoft\PushButtonReset -Name WinREPathScriptSucceed_CVE_2024_20666
if ($value.WinREPathScriptSucceed_CVE_2024_20666 -eq 1)
{
LogMessage("This script was previously run successfully")
exit 1
}
}
}
}
# Get WinRE info
$WinREInfo = Reagentc /info
$findLocation = $False
foreach ($line in $WinREInfo)
{
$params = $line.Split(':')
if ($params.count -le 1)
{
continue
}
if ($params[1].Lenght -eq 0)
{
continue
}
$content = $params[1].Trim()
if ($content.Lenght -eq 0)
{
continue
}
$index = $content.IndexOf("\\?\")
if ($index -ge 0)
{
LogMessage("Find \\?\ at " + $index + " for [" + $content + "]")
$WinRELocation = $content
$findLocation = $True
}
}
if (!$findLocation)
{
LogMessage("WinRE Disabled")
exit 1
}
LogMessage("WinRE Enabled. WinRE location:" + $WinRELocation)
$WinREFile = $WinRELocation + "\winre.wim"
if ([string]::IsNullorEmpty($workDir))
{
LogMessage("No input for mount directory")
LogMessage("Use default path from temporary directory")
$workDir = [System.IO.Path]::GetTempPath()
}
LogMessage("Working Dir: " + $workDir)
$name = "9f8131ee-878f-4525-bf31-e446aac3016a_Mount"
$mountDir = Join-Path $workDir $name
LogMessage("MountDir: " + $mountdir)
# Delete existing mount directory
if (Test-Path $mountDir)
{
LogMessage("Mount directory: " + $mountDir + " already exists")
LogMessage("Try to unmount it")
Dism /unmount-image /mountDir:$mountDir /discard
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Warning: unmount failed: " + $LASTEXITCODE)
}
LogMessage("Delete existing mount direcotry " + $mountDir)
Remove-Item $mountDir -Recurse
}
# Create mount directory
LogMessage("Create mount directory " + $mountDir)
New-Item -Path $mountDir -ItemType Directory
# Set ACL for mount directory
LogMessage("Set ACL for mount directory")
icacls $mountDir /inheritance:r
icacls $mountDir /grant:r SYSTEM:"(OI)(CI)(F)"
icacls $mountDir /grant:r *S-1-5-32-544:"(OI)(CI)(F)"
# Mount WinRE
LogMessage("Mount WinRE:")
Dism /mount-image /imagefile:$WinREFile /index:1 /mountdir:$mountDir
if ($LASTEXITCODE -eq 0)
{
# Patch WinRE
if (PatchPackage -mountDir $mountDir -packagePath $packagePath)
{
$hasUpdated = TargetfileVersionExam($mountDir)
if ($hasUpdated)
{
LogMessage("After patch, find expected version for target file")
}
else
{
LogMessage("Warning: After applying the patch, unexpected version found for the target file")
}
LogMessage("Patch succeed, unmount to commit change")
Dism /unmount-image /mountDir:$mountDir /commit
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Unmount failed: " + $LASTEXITCODE)
exit 1
}
else
{
if ($hasUpdated)
{
if (IsTPMBasedProtector)
{
# Disable WinRE and re-enable it to let new WinRE be trusted by BitLocker
LogMessage("Disable WinRE")
reagentc /disable
LogMessage("Re-enable WinRE")
reagentc /enable
reagentc /info
}
# Leave a breadcrumb indicates the script has succeed
SetRegistrykeyForSuccess
}
}
}
else
{
LogMessage("Patch failed or is not applicable, discard unmount")
Dism /unmount-image /mountDir:$mountDir /discard
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Unmount failed: " + $LASTEXITCODE)
exit 1
}
}
}
else
{
LogMessage("Mount failed: " + $LASTEXITCODE)
}
# Cleanup Mount directory in the end
LogMessage("Delete mount direcotry")
Remove-Item $mountDir -Recurse
こちらの公式サイトよりダウンロードします。
なお、私の環境は、Windows バージョン は 「22H2」。また、パソコン本体のマシンは「 x64-based Systems 」です。
私の場合は「2024-01 Dynamic Update for Windows 10 Version 22H2 for x64-based Systems (KB5034232)」をダウンロードしました。
参考情報:x64-based Systems と ARM64-based Systems と x86-based Systems を判断する方法
ms-settings:about
」で設定画面、システムの詳細情報が開くms-settings:about
詳細情報のページが開き、項目「 デバイスの仕様 」の“システムの種類” で判断可能。
下記の内容で判断
- 表示 “64 ビット オペレーティングシステム、x64 ベース プロセッサ”
結果 「x64-based Systems」
64bitのシステム用。多くのデスクトップPCやラップトップ(ノートパソコン)が該当する。
大半のパソコンは、この環境が該当すると思われる。
- 表示 “64ビット オペレーティングシステム、ARMベース プロセッサ”
結果「ARM64-based Systems」
64bitのシステム用。モバイルデバイス(スマートフォン)や軽量のラックトップが該当する。
- 表示 “32ビット オペレーティングシステム、x86ベース プロセッサ”
結果「x86-based Systems」
32bitのシステム用。最新のパソコンは、ほぼ全て64bitアーキテクチャで販売されているため、
古いパソコンなどが該当する。
仮に間違った環境用の更新プログラムをインストールしようとしても、チェックではじかれて、
エラーになるので間違えを恐れる必要はありません。
下記は、私の環境の「 x64-based Systems 」で確認した画面です。
補足事項:更新プログラム「KB5034232」とは
ここでダウンロードするKB5034232は、冒頭のエラーとなったKB5034441の説明でも記載している通り、本来はKB5034441で自動的に導入される更新プログラムが「KB5034232」です。
エラーとなった KB5034441経由で導入ができないので、手動でKB5034232をダウンロード。
なお、後述していますがこのKB5034232のインストール方法は、PowerShellスクリプトを使ってインストールします。
ファイル名を指定して実行で「powershell」と入力。つづいて「 Ctrl + Shift + Enterキー 」でコマンドプロンプトを管理者権限で実行する。
私の場合、ダウンロードした“PatchWinREScript_2004plus.ps1”を保存した場所「 C:\Users\”ユーザー名”\Downloads 」に移動。
PS C:\WINDOWS\system32> cd "C:\Users\"ユーザー名"\Downloads"
PS C:\Users\"ユーザー名"\Downloads>
.\PatchWinREScript_2004plus.ps1
PS C:\Users\"ユーザー名"\Downloads> .\PatchWinREScript_2004plus.ps1
コマンド パイプライン位置 1 のコマンドレット PatchWinREScript_2004plus.ps1
次のパラメーターに値を指定してください:
(ヘルプを表示するには、「!?」と入力してください。)
packagePath:
PS C:\Users\"ユーザー名"\Downloads> .\PatchWinREScript_2004plus.ps1
コマンド パイプライン位置 1 のコマンドレット PatchWinREScript_2004plus.ps1
次のパラメーターに値を指定してください:
(ヘルプを表示するには、「!?」と入力してください。)
packagePath: "C:\Users\"ユーザー名"\Downloads\windows10.0-kb5034232-x64_ff4651e9e031bad04f7fa645dc3dee1fe1435f38.cab"
01/30/2024 11:13:29 - No input for mount directory
01/30/2024 11:13:30 - Use default path from temporary directory
01/30/2024 11:13:30 - Working Dir: C:\Users\"ユーザー名"\AppData\Local\Temp\
01/30/2024 11:13:30 - MountDir: C:\Users\"ユーザー名"\AppData\Local\Temp\CA551926-299B-27A55276EC22_Mount
01/30/2024 11:13:30 - Create mount directory C:\Users\"ユーザー名"\AppData\Local\Temp\CA551926-299B-27A55276EC22_Mount
ディレクトリ: C:\Users\"ユーザー名"\AppData\Local\Temp
Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 2024/01/30 11:13 CA551926-299B-27A55276EC22_Mount
01/30/2024 11:13:30 - Set ACL for mount directory
処理ファイル: C:\Users\"ユーザー名"\AppData\Local\Temp\CA551926-299B-27A55276EC22_Mount
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
処理ファイル: C:\Users\"ユーザー名"\AppData\Local\Temp\CA551926-299B-27A55276EC22_Mount
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
処理ファイル: C:\Users\"ユーザー名"\AppData\Local\Temp\CA551926-299B-27A55276EC22_Mount
1 個のファイルが正常に処理されました。0 個のファイルを処理できませんでした
01/30/2024 11:13:31 - Mount WinRE:
REAGENTC.EXE: 操作は成功しました。
01/30/2024 11:14:15 - TargetFile: C:\Users\"ユーザー名"\AppData\Local\Temp\CA551926-299B-27A55276EC22_Mount\Windows\System32\bootmenuux.dll
01/30/2024 11:14:15 - Target file version: 10.0.19041.1
01/30/2024 11:14:15 - Windows 10, version 2004
01/30/2024 11:14:15 - Apply package:"C:\Users\"ユーザー名"\Downloads\windows10.0-kb5034232-x64_ff4651e9e031bad04f7fa645dc3dee1fe1435f38.cab"
01/30/2024 11:14:53 - Successfully applied the package
01/30/2024 11:14:53 - Cleanup image
01/30/2024 11:17:38 - Cleanup image succeed
01/30/2024 11:17:38 - TargetFile: C:\Users\"ユーザー名"\AppData\Local\Temp\CA551926-299B-27A55276EC22_Mount\Windows\System32\bootmenuux.dll
01/30/2024 11:17:38 - Target file version: 10.0.19041.2247
01/30/2024 11:17:38 - Windows 10, version 2004
01/30/2024 11:17:38 - Windows 10, version 2004 with revision 2247 >= 2247, updates have been applied
01/30/2024 11:17:38 - After patch, find expected version for target file
01/30/2024 11:17:38 - Patch succeed, unmount to commit change
展開イメージのサービスと管理ツール
バージョン: 10.0.19041.3636
イメージを保存しています
[==========================100.0%==========================]
イメージのマウントを解除しています
[==========================100.0%==========================]
操作は正常に完了しました。
01/30/2024 11:18:42 - Checking BitLocker status
01/30/2024 11:18:43 - Unprotected
01/30/2024 11:18:43 - Bitlocker isn窶冲 enabled on the OS
この操作を正しく終了しました。
01/30/2024 11:18:43 - Delete mount direcotry
PS C:\Users\"ユーザー名"\Downloads>
補足事項:文字化けしているメッセージ「”日時” – Bitlocker isn窶冲 enabled on the OS」について
上記の結果でもわかる通り、「 ~ Bitlocker isn窶冲 enabled ~ 」となっています。
この現象を調べてみた結果、公式サイトに掲載されているPowerShellのコードで全角文字[’
(全角アポストロフィー)]が使用されていることが原因でした。
if (!$protectionEnabled)
{
LogMessage("Bitlocker isn’t enabled on the OS")
return $False
}
この文字化けが発生しても処理自体に影響はありません。ただコンソールに誤って表示されるのみのため、無視してください。
補足情報:対応2-2で紹介されているPowerShellスクリプトの制約について
PowerShellスクリプトでパーティションを拡張する方法(Microsoft公式の手順その2)で紹介されているPowerShellスクリプトについてです。
ざっくりPowerShellのコードを調べると、下記のような制約がありました。
- 再起動直後であること
- OSパーティションの直後にWinRE回復パーティションがあること
※ 直後とは、ディスクの管理上ですぐ右側の事を指す。
- WinRE回復パーティションの空き領域が250MBより小さい事
- WinRE回復パーティションに割り当て可能な空き領域が250MB以上あること
※ WinRE回復パーティションに割り当て可能な空き領域とは、WinRE回復パーティションの直後にある未割り当て領域の事を指す。
- バックアップ先のフォルダーが存在すること
このPowerShell対応するためには、このPowerShellスクリプト + パーティション管理ソフト が必要になるでしょう。
より難易度が高く難しい対応方法となってしまいます。
参考情報:制約が多く実行できなかったPowerShellスクリプト:Resize_script.ps1
2024年3月現在のコードをコピペ。
Param (
[Parameter(Mandatory=$false,HelpMessage="Skip confirmation")][bool]$SkipConfirmation=$false,
[Parameter(Mandatory=$true,HelpMessage="Path to backup old WinRE partition content to")][string]$BackupFolder
)
# ------------------------------------
# Helper functions
# ------------------------------------
# Log message
function LogMessage([string]$message)
{
$message = "$message"
Write-Host $message
}
# Extract numbers from string
function ExtractNumbers([string]$str)
{
$cleanString = $str -replace "[^0-9]"
return [long]$cleanString
}
# Display partition info using fsutil
# Return an array, the first value is total size and the second value is free space
function DisplayPartitionInfo([string[]]$partitionPath)
{
$volume = Get-WmiObject -Class Win32_Volume | Where-Object { $partitionPath -contains $_.DeviceID }
LogMessage(" Partition capacity: " + $volume.Capacity)
LogMessage(" Partition free space: " + $volume.FreeSpace)
return $volume.Capacity, $volume.FreeSpace
}
# Display WinRE status
function DisplayWinREStatus()
{
# Get WinRE partition info
$WinREInfo = Reagentc /info
foreach ($line in $WinREInfo)
{
$params = $line.Split(':')
if ($params.Count -lt 2)
{
continue
}
if (($params[1].Trim() -ieq "Enabled") -Or (($params[1].Trim() -ieq "Disabled")))
{
$Status = $params[1].Trim() -ieq "Enabled"
LogMessage($line.Trim())
}
if ($params[1].Trim() -like "\\?\GLOBALROOT*")
{
$Location = $params[1].Trim()
LogMessage($line.Trim())
}
}
return $Status, $Location
}
# ------------------------------------
# Main execution
# ------------------------------------
# Clear the error
$Error.Clear()
# ------------------------------------
# Examining the system to collect required info
# for the execution
# Need to check WinRE status, collect OS and WinRE
# partition info
# ------------------------------------
LogMessage("Start time: $([DateTime]::Now)")
LogMessage("Examining the system...")
$NeedShrink = $true
$NeedCreateNew = $false
$NeedBackup = $false
# Get WinRE partition info
$InitialWinREStatus = DisplayWinREStatus
$WinREStatus = $InitialWinREStatus[0]
$WinRELocation = $InitialWinREStatus[1]
if (!$WinREStatus)
{
LogMessage("Error: WinRE Disabled")
exit 1
}
# Get System directory and ReAgent xml file
$system32Path = [System.Environment]::SystemDirectory
LogMessage("System directory: " + $system32Path)
$ReAgentXmlPath = Join-Path -Path $system32Path -ChildPath "\Recovery\ReAgent.xml"
LogMessage("ReAgent xml: " + $ReAgentXmlPath)
if (!(Test-Path $ReAgentXmlPath))
{
LogMessage("Error: ReAgent.xml cannot be found")
exit 1
}
# Get OS partition
LogMessage("")
LogMessage("Collecting OS and WinRE partition info...")
$OSDrive = $system32Path.Substring(0,1)
$OSPartition = Get-Partition -DriveLetter $OSDrive
# Get WinRE partition
$WinRELocationItems = $WinRELocation.Split('\\')
foreach ($item in $WinRELocationItems)
{
if ($item -like "harddisk*")
{
$OSDiskIndex = ExtractNumbers($item)
}
if ($item -like "partition*")
{
$WinREPartitionIndex = ExtractNumbers($item)
}
}
LogMessage("OS Disk: " + $OSDiskIndex)
LogMessage("OS Partition: " + $OSPartition.PartitionNumber)
LogMessage("WinRE Partition: " + $WinREPartitionIndex)
$WinREPartition = Get-Partition -DiskNumber $OSDiskIndex -PartitionNumber $WinREPartitionIndex
$diskInfo = Get-Disk -number $OSDiskIndex
$diskType = $diskInfo.PartitionStyle
LogMessage("Disk PartitionStyle: " + $diskType)
# Display WinRE partition size info
LogMessage("WinRE partition size info")
$WinREPartitionSizeInfo = DisplayPartitionInfo($WinREPartition.AccessPaths)
LogMessage("WinRE Partition Offset: " + $WinREPartition.Offset)
LogMessage("WinRE Partition Type: " + $WinREPartition.Type)
LogMessage("OS partition size: " + $OSPartition.Size)
LogMessage("OS partition Offset: " + $OSPartition.Offset)
$OSPartitionEnds = $OSPartition.Offset + $OSPartition.Size
LogMessage("OS partition ends at: " + $OSPartitionEnds)
LogMessage("WinRE partition starts at: " + $WinREPartition.Offset)
$WinREIsOnSystemPartition = $false
if ($diskType -ieq "MBR")
{
if ($WinREPartition.IsActive)
{
LogMessage("WinRE is on System partition")
$WinREIsOnSystemPartition = $true
}
}
if ($diskType -ieq "GPT")
{
if ($WinREPartition.Type -ieq "System")
{
LogMessage("WinRE is on System partition")
$WinREIsOnSystemPartition = $true
}
}
# Checking the BackupFolder parameter
if ($PSBoundParameters.ContainsKey('BackupFolder'))
{
LogMessage("")
LogMessage("Backup Directory: [" + $BackupFolder + "]")
$Needbackup = $true
if ($WinREIsOnSystemPartition)
{
$Needbackup = $false
LogMessage("WinRE is on System partition which will be preserved. No need to backup content")
}
else
{
if (Test-path $BackupFolder)
{
$items = Get-ChildItem -Path $BackupFolder
if ($items)
{
LogMessage("Error: Existing backup directory is not empty")
exit 1
}
}
else
{
LogMessage("Creating backup directory...")
try
{
$item = New-Item -Path $BackupFolder -ItemType Directory -ErrorAction Stop
if ($item)
{
LogMessage("Backup directory created")
}
else
{
LogMessage("Error: Failed to create backup directory [" + $BackupFolder + "]")
exit 1
}
} catch
{
LogMessage("Error: An error occurred: $_")
exit 1
}
}
}
}
# ------------------------------------
# Verify whether we meet requirements of execution
# - WinRE cannot be on OS partition for the extension
# - WinRE partition must be the next partition after OS partition
# - If WinRE partition already have >=250MB free space, no need to do repartition
# - If there is enough unallocated space to grow the WinRE partition size, skip shrinking OS
#
# However, if the WinRE partition is before the OS partition, there is no chance to extend it
# As a result, it's better to create a new WinRE partition after the OS partition
# ------------------------------------
# Perform a few checks
LogMessage("")
LogMessage("Verifying if the WinRE partition needs to be extended or not...")
if (!(($diskType -ieq "MBR") -Or ($diskType -ieq "GPT")))
{
LogMessage("Error: Got an unexpected disk partition style: " +$diskType)
exit 1
}
# WinRE partition must be after OS partition for the repartition
if ($WinREPartitionIndex -eq $OSPartition.PartitionNumber)
{
LogMessage("WinRE and OS are on the same partition, should not perform extension")
exit 0
}
$supportedSize = Get-PartitionSupportedSize -DriveLetter $OSDrive
# if there is enough free space, skip extension
if ($WinREPartitionSizeInfo[1] -ge 250MB)
{
LogMessage("More than 250 MB of free space was detected in the WinRE partition, there is no need to extend the partition")
exit 0
}
if ($WinREPartition.Offset -lt $OSPartitionEnds)
{
LogMessage("WinRE partition is not after OS partition, cannot perform extension")
LogMessage("Need to create a new WinRE partition after OS partition")
$NeedCreateNew = $true
$NeedShrink = $true
# Calculate the size of repartition
# Will create a new WinRE partition with current WinRE partition size + 250 MB
# The OS partition size will be shrunk by the new WinRE partition size
$targetWinREPartitionSize = $WinREPartitionSizeInfo[0] + 250MB
$shrinkSize = [Math]::Ceiling($targetWinREPartitionSize / 1MB) * 1MB
$targetOSPartitionSize = $OSPartition.Size - $shrinkSize
if ($targetOSPartitionSize -lt $supportedSize.SizeMin)
{
LogMessage("Error: The target OS partition size after shrinking is smaller than the supported minimum size, cannot perform the repartition")
exit 1
}
}
else
{
if ($WinREIsOnSystemPartition)
{
LogMessage("WinRE parititon is after the OS partition and it's also System partition")
LogMessage("Error: Got unexpected disk layout, cannot proceed")
exit 1
}
if (!($WinREPartitionIndex -eq ($OSPartition.PartitionNumber + 1)))
{
LogMessage("Error: WinRE partition is not right after the OS partition, cannot extend WinRE partition")
exit 1
}
# Calculate the size of repartition
# Will shrink OS partitition by 250 MB
$shrinkSize = 250MB
$targetOSPartitionSize = $OSPartition.Size - $shrinkSize
$targetWinREPartitionSize = $WinREPartitionSizeInfo[0] + 250MB
$UnallocatedSpace = $WinREPartition.Offset - $OSPartitionEnds;
# If there is unallocated space, consider using it
if ($UnallocatedSpace -ge 250MB)
{
$UnallocatedSpace = $WinREPartition.Offset - $OSPartitionEnds;
LogMessage("Found unallocated space between OS and WinRE partition: " + $UnallocatedSpace)
LogMessage("There is already enough space to extend WinRE partition without shrinking the OS partition")
$NeedShrink = $false
$targetOSPartitionSize = 0
}
else
{
$shrinkSize = [Math]::Ceiling((250MB - $UnallocatedSpace)/ 1MB) * 1MB
if ($shrinkSize > 250MB)
{
$shrinkSize = 250MB
}
$targetOSPartitionSize = $OSPartition.Size - $shrinkSize
if ($targetOSPartitionSize -lt $supportedSize.SizeMin)
{
LogMessage("Error: The target OS partition size after shrinking is smaller than the supported minimum size, cannot perform the repartition")
exit 1
}
}
}
# ------------------------------------
# Report execution plan and ask for user confirmation to continue
# ------------------------------------
# Report the changes planned to be executed, waiting for user confirmation
LogMessage("")
LogMessage("Summary of proposed changes")
if ($NeedCreateNew)
{
LogMessage("Note: WinRE partition is before OS partition, need to create a new WinRE partition after OS partition")
LogMessage("Will shrink OS partition by " + $shrinkSize)
LogMessage(" Current OS partition size: " + $OSPartition.Size)
LogMessage(" Target OS partition size after shrinking: " + $targetOSPartitionSize)
LogMessage("New WinRE partition will be created with size: ", $targetWinREPartitionSize)
if ($WinREIsOnSystemPartition)
{
LogMessage("Existing WinRE partition is also system partition, it will be preserved")
}
else
{
LogMessage("Existing WinRE partition will be deleted")
LogMessage(" WinRE partition: Disk [" + $OSDiskIndex + "] Partition [" + $WinREPartitionIndex + "]")
LogMessage(" Current WinRE partition size: " + $WinREPartitionSizeInfo[0])
}
}
else
{
if ($NeedShrink)
{
LogMessage("Will shrink OS partition by " + $shrinkSize)
LogMessage(" Current OS partition size: " + $OSPartition.Size)
LogMessage(" Target OS partition size after shrinking: " + $targetOSPartitionSize)
if ($UnallocatedSpace -ge 0)
{
LogMessage("Unallocated space between OS and WinRE partition that will be used towards the new WinRE partition: " + $UnallocatedSpace)
}
}
else
{
LogMessage("Will use 250MB from unallocated space between OS and WinRE partition")
}
LogMessage("Will extend WinRE partition size by 250MB")
LogMessage(" WinRE partition: Disk [" + $OSDiskIndex + "] Partition [" + $WinREPartitionIndex + "]")
LogMessage(" Current WinRE partition size: " + $WinREPartitionSizeInfo[0])
LogMessage(" New WinRE partition size: " + $targetWinREPartitionSize)
LogMessage("WinRE will be temporarily disabled before extending the WinRE partition and enabled automatically in the end")
if ($UnallocatedSpace -ge 100MB)
{
LogMessage("Warning: More than 100MB of unallocated space was detected between the OS and WinRE partitions")
LogMessage("Would you like to proceed by using the unallocated space between the OS and the WinRE partitions?")
}
}
if ($Needbackup)
{
LogMessage("")
LogMessage("The contents of the old WinRE partition will be backed up to [" + $BackupFolder + "]")
}
LogMessage("")
LogMessage("Please reboot the device before running this script to ensure any pending partition actions are finalized")
LogMessage("")
if ($SkipConfirmation)
{
LogMessage("User chose to skip confirmation")
LogMessage("Proceeding with changes...")
}
else
{
$userInput = Read-Host -Prompt "Would you like to proceed? Y for Yes and N for No"
if ($userInput -ieq "Y")
{
LogMessage("Proceeding with changes...")
}
elseif ($userInput -ieq "N")
{
LogMessage("Canceling based on user request, no changes were made to the system")
exit 0
}
else
{
LogMessage("Error: Unexpected user input: [" + $userInput + "]")
exit 0
}
}
LogMessage("")
LogMessage("Note: To prevent unexpected results, please do not interrupt the execution or restart your system")
# ------------------------------------
# Do the actual execution
# The main flow is:
# 1. Check whether ReAgent.xml has stage location and clear it for repartiion
# 2. Disable WinRE as WinRE partition will be deleted
# 3. Perform the repartition to create a larger WinRE partition
# 4. Re-enable WinRE
# ------------------------------------
LogMessage("")
# Load ReAgent.xml to clear Stage location
LogMessage("Loading [" + $ReAgentXmlPath + "] ...")
$xml = [xml](Get-Content -Path $ReAgentXmlPath)
$node = $xml.WindowsRE.ImageLocation
if (($node.path -eq "") -And ($node.guid -eq "{00000000-0000-0000-0000-000000000000}") -And ($node.offset -eq "0") -And ($node.id -eq "0"))
{
LogMessage("Stage location info is empty")
}
else
{
LogMessage("Clearing stage location info...")
$node.path = ""
$node.offset = "0"
$node.guid= "{00000000-0000-0000-0000-000000000000}"
$node.id="0"
# Save the change
LogMessage("Saving changes to [" + $ReAgentXmlPath + "]...")
$xml.Save($ReAgentXmlPath)
}
# Disable WinRE
LogMessage("Disabling WinRE...")
reagentc /disable
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Warning: encountered an error when disabling WinRE: " + $LASTEXITCODE)
exit $LASTEXITCODE
}
# Verify WinRE is under C:\Windows\System32\Recovery\WinRE.wim
$disableWinREPath = Join-Path -Path $system32Path -ChildPath "\Recovery\WinRE.wim"
LogMessage("Verifying that WinRE wim exists in downlevel at default location")
if (!(Test-Path $disableWinREPath))
{
LogMessage("Error: Cannot find " + $disableWinREPath)
# Re-enable WinRE
LogMessage("Re-enabling WinRE on error...")
reagentc /enable
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Warning: encountered an error when enabling WinRE: " + $LASTEXITCODE)
}
exit 1
}
# ------------------------------------
# Perform the repartition
# 1. Resize the OS partition
# 2. Delete the WinRE partition
# 3. Create a new WinRE partition
# ------------------------------------
LogMessage("Performing repartition to extend the WinRE partition ...")
# 1. Resize the OS partition
if ($NeedShrink)
{
LogMessage("Shrinking the OS partition to create a larger WinRE partition")
LogMessage("Resizing the OS partition to: [" + $targetOSPartitionSize + "]...")
Resize-Partition -DriveLetter $OSDrive -Size $targetOSPartitionSize
if ($Error.Count -gt 0) {
LogMessage("Error: Resize-Partition encountered errors: " + $Error[0].Exception.Message)
# Re-enable WinRE
LogMessage("Re-enabling WinRE on error...")
reagentc /enable
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Warning: encountered an error when enabling WinRE: " + $LASTEXITCODE)
}
exit 1
}
$OSPartitionAfterShrink = Get-Partition -DriveLetter $OSDrive
LogMessage("Target partition size: " + $targetOSPartitionSize)
LogMessage("Size of OS partition after shrinking: " + $OSPartitionAfterShrink.Size)
}
# 2. Delete the WinRE partition
LogMessage("")
if ($WinREIsOnSystemPartition)
{
LogMessage("Existing WinRE partition is System partition, skipping deletion")
}
else
{
# If requested by user, backup rest of the content on WinRE partition to backup directory
if ($Needbackup)
{
$sourcePath = $WinREPartition.AccessPaths[0]
LogMessage("Copying content on WinRE partition from [" + $sourcePath + "] to [" + $BackupFolder + "]...")
# Copy-Item may have access issue with certain system folders, enumerate the children items and exlcude them
$items = Get-ChildItem -LiteralPath $sourcePath -Force
foreach ($item in $items)
{
if ($item.Name -ieq "System Volume Information")
{
continue
}
$sourceItemPath = Join-Path -Path $sourcePath -ChildPath $item.Name
$destItemPath = Join-Path -Path $BackupFolder -ChildPath $item.Name
try
{
LogMessage("Copying [" + $sourceItemPath + "] to [" + $destItemPath + "]...")
Copy-Item -LiteralPath $sourceItemPath -Destination $destItemPath -Recurse -Force
} catch
{
LogMessage("Error: An error occurred during copy: $_")
exit 1
}
}
LogMessage("Backup completed")
LogMessage("")
}
LogMessage("Deleting WinRE partition: Disk [" + $OSDiskIndex + "] Partition [" + $WinREPartitionIndex + "]...")
Remove-Partition -DiskNumber $OSDiskIndex -PartitionNumber $WinREPartitionIndex -Confirm:$false
if ($Error.Count -gt 0) {
LogMessage("Error: Remove-Partition encountered errors: " + $Error[0].Exception.Message)
exit 1
}
}
# A short sleep for the partition change
Sleep 5
# 3. Create a new WinRE partition
LogMessage("")
LogMessage("Creating new WinRE partition...")
LogMessage("Target size: " + $targetWinREPartitionSize)
if ($diskType -ieq "GPT")
{
$partition = New-Partition -DiskNumber $OSDiskIndex -Size $targetWinREPartitionSize -GptType "{de94bba4-06d1-4d40-a16a-bfd50179d6ac}"
$newPartitionIndex = $partition.PartitionNumber
# A short sleep to make sure the partition is ready for formatting
Sleep 2
LogMessage("Formating the partition...")
$result = Format-Volume -Partition $partition -FileSystem NTFS -Confirm:$false
if ($Error.Count -gt 0) {
LogMessage("Error: Format-Volume encountered errors: " + $Error[0].Exception.Message)
exit 1
}
}
else
{
#$partition = New-Partition -DiskNumber $OSDiskIndex -Size $targetWinREPartitionSize -MbrType 0x27
$targetWinREPartitionSizeInMb = [int]($targetWinREPartitionSize/1MB)
$diskpartScript =
@"
select disk $OSDiskIndex
create partition primary size=$targetWinREPartitionSizeInMb id=27
format quick fs=ntfs label="Recovery"
set id=27
"@
$TempPath = $env:Temp
$diskpartSciptFile = Join-Path -Path $TempPath -ChildPath "\ExtendWinRE_MBR_PowershellScript.txt"
LogMessage("Creating temporary diskpart script to create Recovery partition on MBR disk...")
LogMessage("Temporary diskpart script file: " + $diskpartSciptFile)
$diskpartScript | Out-File -FilePath $diskpartSciptFile -Encoding ascii
LogMessage("Executing diskpart script...")
try
{
$diskpartOutput = diskpart /s $diskpartSciptFile
if ($diskpartOutput -match "DiskPart successfully")
{
LogMessage("Diskpart script executed successfully")
}
else
{
LogMessage("Error executing diskpart script:" + $diskpartOutput)
exit 1
}
LogMessage("Deleting temporary diskpart script file...")
Remove-Item $diskpartSciptFile
}
catch
{
LogMessage("Error executing diskpart script: $_")
exit 1
}
$vol = Get-Volume -FileSystemLabel "Recovery"
$newPartitionIndex = (Get-Partition | Where-Object { $_.AccessPaths -contains $vol.Path } ).PartitionNumber
}
if ($Error.Count -gt 0)
{
LogMessage("Error: New-Partition encountered errors: " + $Error[0].Exception.Message)
exit 1
}
LogMessage("New Partition index: " + $newPartitionIndex)
# Re-enable WinRE
LogMessage("Re-enabling WinRE...")
reagentc /enable
if (!($LASTEXITCODE -eq 0))
{
LogMessage("Warning: encountered an error when enabling WinRE: " + $LASTEXITCODE)
exit $LASTEXITCODE
}
# In the end, Display WinRE status to verify WinRE is enabled correctly
LogMessage("")
LogMessage("WinRE Information:")
$FinalWinREStatus = DisplayWinREStatus
$WinREStatus = $FinalWinREStatus[0]
$WinRELocation = $FinalWinREStatus[1]
if (!$WinREStatus)
{
LogMessage("Warning: WinRE Disabled")
}
$WinRELocationItems = $WinRELocation.Split('\\')
foreach ($item in $WinRELocationItems)
{
if ($item -like "partition*")
{
$WinREPartitionIndex = ExtractNumbers($item)
}
}
LogMessage("WinRE Partition Index: " + $WinREPartitionIndex)
$WinREPartition = Get-Partition -DiskNumber $OSDiskIndex -PartitionNumber $WinREPartitionIndex
$WinREPartitionSizeInfoAfter = DisplayPartitionInfo($WinREPartition.AccessPaths)
LogMessage("")
LogMessage("OS Information:")
$OSPartition = Get-Partition -DriveLetter $OSDrive
LogMessage("OS partition size: " + $OSPartition.Size)
LogMessage("OS partition Offset: " + $OSPartition.Offset)
if (!($WinREPartitionIndex -eq $newPartitionIndex))
{
LogMessage("Warning: WinRE is installed to partition [" + $WinREPartitionIndex +"], but the newly created Recovery partition is [" + $newPartitionIndex + "]")
}
LogMessage("End time: $([DateTime]::Now)")
if ($NeedBackup)
{
LogMessage("")
LogMessage("The contents of the old WinRE partition has been backed up to [" + $BackupFolder + "]")
}
LogMessage("")
LogMessage("Successfully completed the operation")
対応3.Windows 11 に アップグレードする方法
この方法は、公式には紹介されていない方法であり、すべての環境で解消されるかは不明です。
OSのアップグレードはリスクの大きい作業となります。必要に応じてバックアップの取得なども検討してください。
また、意外と見落としがちな観点ですが、作業者が誤ってパソコンの電源を落としてしまう他に、
「落雷による突発的な停電」や「家電を使いすぎてブレーカーが落ちる」なども注意が必要です。
ヒント:開閉できるエリア
下記のようなエリアはクリックすると開閉可能っピ 👍
対応3.Windows 11 に アップグレードする方法
Windows OS のアップグレードは、作業時点で配信されている更新プログラムをすべてインストールしたほうが安全です。
今回、エラーとなったKB5034441以外の更新プログラムはインストールしましょう。
回復パーティションの空き領域は「529 MB」の環境です。
理由はわかりませんが、250 MB 以上なのに今回のエラーが発生しました。
Windows 11 のシステム要件を満たしている場合は、Windows Update 上に “Windows 11 の準備ができました。” というメッセージが表示されます。
そのメッセージに「ダウンロードしてインストール」ボタンがあります。
補足情報:システム要件を満たしているのに上記の画面が表示されない場合
もしかすると、以前に「今は Windows 10 の使用を継続します」をクリックした事により、
上記のようなWindows 11 アップグレードのメッセージが非表示状態になっているのかもしれません。
Windows Update 画面の右側メニューにある「インストールの準備が完了したかどうかを確認する」をクリックすると メッセージが再表示されるようになります。
なお、Windows Update 画面の右側メニューがそもそも表示されていないという方は、Windows Update 画面の横サイズを大きくする事で右側のメニューが表示されると思います。
Windows 11 のOSデータがダウンロード後、ソフトウェア ライセンス条項が表示。
このボタンを押すとWindows Update 画面上でインストール処理が開始されます。
このインストール処理が完了後、自動でWindows OSが再起動されてしまうので、
ドキュメントを開いている場合は保存してから進めてください。
Windows 11 OS をインストール(アップグレード)中にも操作できますが、
極力、触らない方が良いです。
あと、操作しなくても画面は定期的にチェックする事をオススメします!
なぜ見る必要があるかというと、仮にエラーが発生してしまった場合の事を想定しているため。
どのような流れでエラーが発生したかという情報は、問題を切り分けるうえで重要な手がかりとなります。
ずっと画面に張り付いて見る必要はありませんが、定期的にチェックしましょう。
エラーが発生していた更新プログラム「KB5034441」のエラーが表示されていない事を確認。
※ 更新プログラム「KB5034441」は、Windows 10 向けの更新プログラムだったので、アップグレードによりエラーが解消しています。
上記の画面でもわかる通り、Windows 11 へのアップグレードにより「システムドライブのCドライブは縮小」し、「Windows 11 用の回復パーティションが新規作成」された状態になりました。
(自動で実行されているので、環境によって結果は変化。)
総容量 | 回復パーティション(Windows 10用) | EFI システム パーティション | システムドライブ(Cドライブ) | 回復パーティション(Windows 11用) | |
---|---|---|---|---|---|
事前 | 931.50 GB | 529 MB | 99 MB | 930.88 GB | なし |
事後 | 931.50 GB | 529 MB | 99 MB | 930.88 GB 930.08 GB | なし 818 MB |
参考情報:Windows 11 にアップグレードできるシステム要件
- プロセッサ(CPU)
1 ギガヘルツ (GHz) 以上で 2 コア以上の64 ビット互換プロセッサまたは System on a Chip (SoC)。
- メモリ
4 ギガバイト (GB) 以上
- ストレージ(HDD・SSD)
64 GB 以上の記憶装置
- システム ファームウェア
UEFI、セキュア ブート対応
- TPM
トラステッド プラットフォーム モジュール (TPM) バージョン 2.0
- グラフィックス カード
DirectX 12 以上 (WDDM 2.0 ドライバー) に対応
- ディスプレイ
対角サイズ 9 インチ以上で 8 ビット カラーの高解像度 (720p) ディスプレイ
- インターネット接続と Microsoft アカウント
個人向け Windows 11 Pro と Windows 11 Home は、初期設定時にインターネット接続と Microsoft アカウントが必要。
Windows 11 Home の S モードを解除する場合もインターネット接続が必要。
すべての Windows 11 エディションで、更新の実行、ダウンロード、一部の機能を使用するために、インターネットのアクセスが必要。
一部の機能を利用するにはMicrosoft アカウント が必要。
まとめ
- Windows 10 で 配信されている更新プログラム「KB5034441」は、
- Windows 10 向けの更新プログラムであること
- WinRE(回復パーティション)の脆弱性をつき、一部エディションで使用できるセキュリティ機能、BitLockerの保護がすり抜けられてしまう可能性がある問題の対策
- KB5034441のエラー「0x80070643」は、
- Windows OS がインストールされているディスクと同じ場所に自動作成されているWinRE回復パーティションの空き領域が250 MB 以上ない為、エラーが発生。
(理由は不明だが一部、例外的な環境もあり。)
- Windows OS がインストールされているディスクと同じ場所に自動作成されているWinRE回復パーティションの空き領域が250 MB 以上ない為、エラーが発生。
- 2024年3月現在、エラーの対応方法はおおきくわけて3つある
- 対応1.エラーが発生している更新プログラムを一時的に非表示にする方法
BitLockerが使用できるエディション、かつBitLockerを有効にしている環境が対象となる問題。
その為、BitLockerを使用していないのであれば、無理して対応する必要がない。
Windows Update 画面でエラーが表示されるのが気になる方は、一時的に更新プログラム「KB5034441」を非表示できる。
- 対応2.回復パーティションを拡張して更新プログラムを導入する方法
対応2-1 と 対応2-3 で対応可能。
対応2-2 で紹介されているPowerShellスクリプトは制約が多く使用不可。- 対応2-1.手動でパーティションの拡張を行う方法
対応2-2.PowerShellスクリプトでパーティションを拡張する方法- 対応2-3.WinREを再構成する方法
- 対応3.Windows 11 に アップグレードする方法
- 対応1.エラーが発生している更新プログラムを一時的に非表示にする方法
繰り返しにはなりますが、この更新プログラムは、Windowsの一部エディションで有効にできるBitLocker機能に関連した問題です。
そもそもBitLockerを使えないエディションだったり、BitLockerを有効にしていない環境だった場合、問題が発生しません。
私個人の見解としては無理して、いま対応する必要はないと思っています。
今後、Microsoftより正式な対応方法が公開されると思います。気長に待ちましょう。
コメント