プログラマーのメモ書き

伊勢在住のプログラマーが気になることを気ままにメモったブログです

Windows 11 での回復パーティションの作成

仮想マシンの Windows 10 -> 11 の一連の記事になります。

仮想マシンの Windows 10 を 11 に上げた際、回復パーティションがインストールされるものと思っていたら、下記のようになぜかインストールされていませんでした。

あれ?

不思議に思って、確認すると

C:\Windows\System32>reagentc /info
Windows 回復環境 (Windows RE) およびシステム リセット構成
情報:

    Windows RE の状態:         Enabled
    Windows RE の場所:         \\?\GLOBALROOT\device\harddisk0\partition2\Recovery\WindowsRE
    ブート構成データ (BCD) ID: 75289607-56f5-11ef-9409-8b3b7980074f
    回復イメージの場所:
    回復イメージ インデックス: 0
    カスタム イメージの場所:
    カスタム イメージ インデックス: 0

REAGENTC.EXE: 操作は成功しました。


C:\Windows\System32>

問題なくインストールされており、有効になっていました。

ん?

上記のパーティション2というのは、 C ドライブがあるパーティションになります。ということは、回復パーティションではなく、 C ドライブ内にファイルとして存在しているということかな?

念のため調べてみると、 C ドライブの直下にファイルがありますね。

C:\Windows\System32>dir \Recovery\WindowsRE /a
 ドライブ C のボリューム ラベルがありません。
 ボリューム シリアル番号は 9E81-C952 です

 C:\Recovery\WindowsRE のディレクトリ

2024/08/10  18:50    <DIR>          .
2024/08/10  17:49    <DIR>          ..
2022/05/07  14:19         3,170,304 boot.sdi
2024/08/10  18:50             1,106 ReAgent.xml
2024/08/10  17:51       807,408,049 Winre.wim
               3 個のファイル         810,579,459 バイト
               2 個のディレクトリ  15,094,202,368 バイトの空き領域

C:\Windows\System32>

推測ですが、この仮想マシンの場合は、こちらの記事の最後で触れたように、 Windows 11 にアップグレードする際、再起動が少しうまくいかなかった経緯があります。この辺りが、回復パーティションが作られるのではなく、ファイルとして有効になっている点と関係があるのかも知れません。

いずれにしても、回復環境を回復パーティションに戻したいと思います。

作業は Windows 10 ですが、回復パーティションについていろいろと試していた下記の記事を参考にすすめました。

blog.mori-soft.com

回復環境の無効化

まずは、回復環境を無効化します。

C:\Windows\System32>reagentc /disable
REAGENTC.EXE: 操作は成功しました。


C:\Windows\System32>

無効化すると C:\Windows\System32\Recovery 以下に Winre.wim が作られていました。

回復パーティションの作成

まずは、Cドライブを縮小します。

DISKPART> select disk 0

ディスク 0 が選択されました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    システム               101 MB  1024 KB
  Partition 2    プライマリ               79 GB   102 MB

DISKPART> select partition 2

パーティション 2 が選択されました。

DISKPART> shrink minimum=563

ボリュームは、次の方法で正常に縮小されました:  563 MB

DISKPART>

ちゃんと空きましたね。縮小するサイズは、 Windows 10 の時に存在していた回復パーティションのサイズと同じにしました。

次に回復パーティションを作成します。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    システム               101 MB  1024 KB
* Partition 2    プライマリ               79 GB   102 MB

DISKPART> create partition primary

DiskPart は指定したパーティションの作成に成功しました。

DISKPART> format quick fs=ntfs

  100% 完了しました

DiskPart は、ボリュームのフォーマットを完了しました。

DISKPART> set id=de94bba4-06d1-4d40-a16a-bfd50179d6ac

DiskPart は、パーティション ID を設定しました。

DISKPART> gpt attributes=0x8000000000000001

選択された GPT パーティションに DiskPart で属性を割り当てました。

DISKPART>

GPT と MBR で設定方法が若干違うのでその点だけ注意が必要です。これで、回復パーティションとして、認識されました。

最後に回復環境を復元します。

C:\Windows\System32>reagentc /enable
REAGENTC.EXE: 操作は成功しました。


C:\Windows\System32>

確認

コマンドプロンプトから、

C:\Windows\System32>shutdown /r /o /t 0 

として再起動して、『トラブルシューティング』->『詳細オプション』を選択し、各種オプションが表示されていることを確認します。

問題ないですね。

Windows 10 を 11 にアップグレードする際に EFI パーティションが邪魔になった話

仮想マシンの Windows 10 -> 11 の一連の記事になります。

こちらの記事で、 VirtualBox 上の仮想マシンを Windows 10 から 11 へのアップグレードする話をまとめました。

で、同じことを別の仮想マシン(こちらの記事で VMDK から VDI に変換していたやつ)についても、アップグレードをやってみると、あら不思議、 GPT ディスクに変更したタイミングで、 C ドライブがあるパーティションの後ろに EFI パーティションが作られていました。

何じゃこりゃ?

最初に Windows 11 へのアップグレードを試したやつ(こちらの記事参照)を確認すると、EFIパーティションが先頭に作られていました。

何が違うんだろうか?まあ、詳しい理由は不明ですが、 C ドライブのパーティションの後ろに、EFI パーティションが作られることがあるようですね。

でも、このままだとシステムパーティションが拡張できないので、いまのままだと容量不足で Windows 11 へのアップグレードができません。

ということで、 EFI パーティションを移動させて、 C ドライブを拡張したので、その顛末をメモっておきます。

EFI パーティションの移動

ネットを調べてみると、同じようなことに困っている人がたくさんいるようで、いろいろな記事を見つけることができました。中でも、わかりやすかったので、下記の記事を元に作業を行いました。

Moving EFI partition before C:

おおまかにいうと、 EFI パーティションを移動させるのではなく、新しい EFI パーティションを前方に作って、その後古い EFI パーティションを削除するという方法になります。

(参考)

なお、EFI パーティションの移動に関する記事は他にもいろいろありました。

ご自分のわかりやすいものを参考にしてください。

準備

まず、準備として GParted Live というツールを入手しておきます。名前に聞き覚えがあるなと思ったら、昔 Linux インストールするときとかにお世話になったやつですね。

GParted -- Live CD/USB/PXE/HD

とりあえず、 iso イメージをダウンロードしておきます。

次に、今回見つけた記事に注記として書いてあるように、今の EFI パーティションの後方にある空き領域にダミーのボリュームを作成しておきます。

とりあえず、これで準備完了です。

パーティションの操作

仮想マシンの Windows 10 を起動します。コマンドプロンプトを管理者権限で開いて、 diskpart コマンドで操作していきます。

まずは、 C ドライブの直後に空き領域を作ります。

DISKPART> select disk 0

ディスク 0 が選択されました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    プライマリ               59 GB  1024 KB
  Partition 2    システム               100 MB    59 GB
  Partition 3    回復                 563 MB    59 GB
  Partition 4    プライマリ               20 GB    59 GB

DISKPART> select partition 1

パーティション 1 が選択されました。

DISKPART> shrink desired=100

ボリュームは、次の方法で正常に縮小されました:  100 MB

DISKPART>

今回の場合は、パーティション1というのがCドライブがあるパーティションになります。操作結果はこんな感じになります。

一度、シャットダウンして、次は GParted での操作になります。

GParted を起動

仮想マシンの CD ドライブとして、先ほどダウンロードした GParted Live の iso ファイルを割り当てます。

これで、起動してくれればいいんですが、 EFI の Windows の場合、VirtualBox のブート順が無視されるそうです。

How to Boot from ISO on VirtualBox EFI machine. - WinTips.org

このため、 CD にセットした iso イメージを立ち上げるためには、仮想マシンを立ち上げたら、 ECS キーを連打します。

うまくいくと、上のような画面が表示されるので、 Boot Manager を選択します。すると、下記のような、どのメディアから起動するかの選択画面が表示されるので、

VirtualBox の CD を選択します。すると、 GParted Live の起動メニューが表示されます。

特に問題なければ、一番上のデフォルト設定の GParted を起動します。

起動時にキーマップ、言語、 UI などを聞かれますが、言語以外はデフォルトにして、言語は日本語を選択して起動します。無事に起動すると下記のような画面が表示されます。

Cドライブのあるパーティションの移動

さきほど、 C ドライブの後ろに空き領域を作ったので、 GParted で Cドライブがあるパーティションを後ろに移動させて、前方に空き領域を作ります。

C ドライブのあるパーティション( /dev/sda1)を選択して、『リサイズ/移動』をクリックすると

のような画面が表示されます。

  • 前方の空き容量が 0 MB
  • 後方の空き容量が 101MB

となっているので、これを入れ替えるようにします。

『リサイズ/移動』ボタンを押してのち、実行をすると、

のような警告がでますが、そのまま続けます。最終的に、

のような形になれば終わりです。

GParted を終了し、CD の iso ファイル設定を解除後、再度 Windows を起動します。Windows 上でパーティションをみると

こんな感じなってました。

新しい EFI パーティションの作成

Windows が起動したら、再度コマンドプロンプトを管理者権限で立ち上げて、 diskpart で操作を行います。

DISKPART> select disk 0

ディスク 0 が選択されました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    プライマリ               59 GB   102 MB
  Partition 2    システム               100 MB    59 GB
  Partition 3    回復                 563 MB    59 GB
  Partition 4    プライマリ               20 GB    59 GB

DISKPART> create partition efi

DiskPart は指定したパーティションの作成に成功しました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
* Partition 5    システム               101 MB  1024 KB
  Partition 1    プライマリ               59 GB   102 MB
  Partition 2    システム               100 MB    59 GB
  Partition 3    回復                 563 MB    59 GB
  Partition 4    プライマリ               20 GB    59 GB

DISKPART>

パーティションを作成する際に、容量を指定しない場合は最大のサイズで作成してくれるとのことです。次に、作成した EFI パーティションをフォーマットしておきます。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
* Partition 5    システム               101 MB  1024 KB
  Partition 1    プライマリ               59 GB   102 MB
  Partition 2    システム               100 MB    59 GB
  Partition 3    回復                 563 MB    59 GB
  Partition 4    プライマリ               20 GB    59 GB

DISKPART> format quick fs=fat32

  100% 完了しました

DiskPart は、ボリュームのフォーマットを完了しました。

DISKPART> assign letter=x

DiskPart はドライブ文字またはマウント ポイントを正常に割り当てました。

DISKPART>

ここで EFI パーティションにドライブレター(上記では x: )を割り当てておきます。Windows で見ても EFI パーティションとして認識されてますね。

diskpart を終了し、最後に EFI パーティションに起動関連のファイルを作成します。

C:\WINDOWS\system32>bcdboot C:\Windows /s x:
ブート ファイルは正常に作成されました。

C:\WINDOWS\system32>

ここまでで、 EFI パーティションの作成は完了です。一度シャットダウンして、問題なく起動できることを確認します。

パーティションを整理

問題なく Windows が起動できれば、最後に古い EFI パーティションや不要なパーティションを削除しておきます。また、 C ドライブの容量も増やして、 Windows 11 のインストール要件を満たすようにします。

ここでも、コマンドプロンプトから diskpart を呼び出して実行します。

DISKPART> select disk 0

ディスク 0 が選択されました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    システム               101 MB  1024 KB
  Partition 2    プライマリ               59 GB   102 MB
  Partition 3    システム               100 MB    59 GB
  Partition 4    回復                 563 MB    59 GB
  Partition 5    プライマリ               20 GB    59 GB

DISKPART> select partition 3

パーティション 3 が選択されました。

DISKPART> delete partition override

DiskPart は選択されたパーティションを正常に削除しました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    システム               101 MB  1024 KB
  Partition 2    プライマリ               59 GB   102 MB
  Partition 4    回復                 563 MB    59 GB
  Partition 5    プライマリ               20 GB    59 GB

DISKPART> select partition 4

パーティション 4 が選択されました。

DISKPART> delete partition override

DiskPart は選択されたパーティションを正常に削除しました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    システム               101 MB  1024 KB
  Partition 2    プライマリ               59 GB   102 MB
  Partition 5    プライマリ               20 GB    59 GB

DISKPART> select partition 5

パーティション 5 が選択されました。

DISKPART> delete partition

DiskPart は選択されたパーティションを正常に削除しました。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    システム               101 MB  1024 KB
  Partition 2    プライマリ               59 GB   102 MB

DISKPART> 

上記の操作は、

  • パーティション3は、古いEFIパーティション
  • パーティション4は、回復パーティション
  • パーティション5は、ダミーのパーティション

なので、これらをすべて削除するというものです(回復パーティションはこのあと Windows 11 をインストールする際に、 C ドライブの拡張が簡単にできるように消してしまいました)。

最後に C ドライブを拡張しておきます。

DISKPART> list partition

  Partition ###  Type                Size     Offset
  -------------  ------------------  -------  -------
  Partition 1    システム               101 MB  1024 KB
* Partition 2    プライマリ               59 GB   102 MB

DISKPART> select partition 2

パーティション 2 が選択されました。

DISKPART> extend

DiskPart はボリュームを正常に拡張しました。

DISKPART>

こんな感じになりました。

まとめ

ここまで操作ができると、この仮想マシンの場合は、Windows11 が OK となりました。

あとは、前回の記事の通り、 Windows 11 をインストールしてやればOKです。なお、インストールの時、再起動がうまくいかないなど若干不安な点もありましたが、無事に立ち上がるようになりました。

flutter アプリを iPhone でデバッグ動作させた際に、ローカルネットワーク接続の確認ダイアログが表示された

こちらの記事に書いたように、 Mac 上の Flutter の開発環境を更新して、ビルドできるようにしました。で、実機をつないでデバッグビルドを動かすと、

という確認ダイアログが表示されました。

あれれ?以前はこんなの表示されていなかったと思うんだけどな?ということで、簡単に調べてみたので、まとめておきます。

なお、環境としては、

  • XCode 15.4
  • Mac mini (2018), MacOS Soxxxx 15.4
  • iPhone SE v2, iOS 16.7.2 (当初は iOS 15)

になります。後述する、エラー対応後のテスト時は、 iOS のアップデートがあったため、

  • iOS 17.5.1

になってます。

ダイアログの内容

改めてダイアログの内容を確認してみます。文章を読んでみると、

デバッグ時のみ Flutter アプリがローカルネットワーク上のデバイスの検索等を行うのでその許可を求める

という内容のようです。英文の最後に、リリースビルドではこのダイアログは表示されない、という旨の注記もあるように、どうも開発時のみに表示されるようです。 iOS 14 で導入された確認ダイアログになるそうです。

App がローカルネットワーク上のデバイスへの接続を求めてくる場合 - Apple サポート (日本)

ネットをググると、いくつか開発系の記事でこのダイアログが表示されることを述べています。

これって、 Flutter のバージョンに寄るのかな?と思い調べてみると、 Flutter 1.22 で iOS 14 対応があり、この時からデバッグ時にこの権限確認ダイアログが表示されるようになったっぽいです。

でも、 Flutter 1.22 より新しいバージョンで何度もデバッグビルドしてたはずなんだけど、なんでいまさら権限の確認ダイアログが表示されたんだろうか?それとも、以前も表示されていたけど、特に気にせずに許可してしまっていたんだろうか?

そのあたりは謎ですが、まあ、そういう権限の確認が求められたという話です。

デバッグビルド実行時のエラー

さて、権限の確認ダイアログについては上記の通りなんですが、 XCode でビルドして実機でデバッグビルドを動かした際に、ダイアログで『許可』を選択後も、ログに以下のエラーが表示されていました。

[ERROR:flutter/shell/platform/darwin/ios/framework/Source/FlutterDartVMServicePublisher.mm(126)] On iOS 14+, local network broadcast in apps need to be declared in the app's Info.plist. Debug and profile Flutter apps and modules host VM services on the local network to support debugging features such as hot reload and DevTools. To make your Flutter app or module attachable and debuggable, add a 'dartVmService.tcp' value to the 'NSBonjourServices' key in your Info.plist for the Debug/Profile configurations. For more information, see https://flutter.dev/docs/development/add-to-app/ios/project-setup#local-network-privacy-permissions

ああ、どうもローカルネットワークのデバイスとの通信を行うなら、 Info.plist にその旨宣言しておけ、ということのようです。

にしても、 iOS 14 対応で、権限の確認ダイアログ出すようにしたんだったら、 Flutter プロジェクト作成時にデフォルトでこの宣言も含めておいてほしいですね。昔作ったやつなので、抜けてるんだろうか?新しい Flutter SDK でプロジェクトを作ったら含まれているのかな?ちょっとそこまで検証してないのでわからないです。

あと、このエラーが出力されたままでも実機で動作できてるし、このままにしとこうかな?とも思ったのですが、やっぱり、エラーは潰しておくことにします。

ということで、エラーメッセージに出ている下記の参考 URL に従って、作業しておきます。

Integrate Flutter | Flutter

なお、公式の説明だけだと今一つわかりにくいところもあったので、下記の記事なども参考にしました。

[HowTo] enable Local Network Privacy Permissions on iOS14+ - DEV Community

新しい Info.plist の作成

参考 URL では、新規に Info.plist ファイルを作成するときの手順が載ってます。でも、すでに Info.plist があるので、ここは、ファイルのコピーを使って、複製してしまいます。

XCode のプロジェクトナビゲーターで Info.plist を選択した状態にして

メニューの File -> Duplicate を選択します。

ファイル名を聞かれるので、 Info-Debug.plist として、

『Save』ボタンを押します。これで、ファイルが追加されました。

次に、元のファイルのファイル名を Info-Release.plist に変更します。プロジェクトナビゲーターで既存の Info.plist を選択して、画面右端の Identity and Type の Name に新しい名前(今回は Info-Release.plist )を入力します。

設定が完了すると、下記のように、2つの Info.plist ファイルが作成された状態になります。

Info-Debug.plist の変更

次に、作成した Info-Debug.plist の内容を編集します。プロジェクトナビゲーターで Info-Debug.plist を選択して、中央のエディタ部分で、 Information Property List にカーソルを合わせると、+ボタンが表示されるので、クリックします。

ドロップダウンリストが表示されるので、『Bonjour Services』を選択します。次に、配列の値として『dartVmService.tcp』を入力します。

これで、 OK です。

Build Settings を変更

デバッグ・リリースなどの各ビルドでどの Info.plist を利用するかの設定を変更します。

プロジェクトナビゲーターから、プロジェクトを選択し、 TARGETS で Runner を選択し、 Build Settings タブを選択し、 Packaging を開きます。

ここで、参考 URL では、Info.plist File を選択して、値として Info-$(CONFIGURATION).plist と入力するようになっています。これで設定すると、

のように、それぞれの Configuration に対応した Info.plist が自動的に設定されます。

でも、今回は Info-Profile.plist を作っていませんし、作る気も今のところありません。なので、この方法ではなく、各 Configuration ごとにファイル名を個別に指定することにします。

なお、 Profile に対しても、 ローカルネットワークの宣言が必要になるので、 Info-Debug.plist を指定しておきます。

(参考)XCode のビルドの指定方法について

今回ビルド周りの設定を見ていて、単純に、デバッグとリリースの2種類があるというわけではないということがわかりました。

これらの記事にあるように、 Target, Scheme, Configuration の3つの設定により定義されるということのようです。

Target というのはいわゆるビルドフレーバーというのに該当するっぽくて、作成するアプリの内容そのものを切り替えるためのものですね。Configuration というのが、いわゆるビルド設定に該当するもののようで、ビルドオプションや環境変数などの各種設定値を切り替えるための設定になるようです。

で、 Scheme が、 Target と Configuration をまとめたものになり、XCode のメニューからコマンドを実行した際に、選択している Scheme の内容に応じて実行されるというもののようです。なので、実際、 Scheme の編集画面をみてみると、

のように、メニューのコマンドに対応した設定内容になっています。

現在の Flutter プロジェクトの場合、

  • Schemeとして Runner というものが1つだけ定義
  • Target として Runner というものが1つだけ定義
  • Configuration として Debug / Profile / Release というものが3つ定義

されています。

なお、今後、環境設定を色々と触るなら、下記の記事なども参考になりそうです。

XcodeでDevelop/Staging/Release環境を上手に切り分ける方法 #Xcode - Qiita

(参考2)ビルドの種類について

上記でも触れていますが、 Configuration として、 Profile というのがあるということに改めて気がつきました。これなんだろうか?と思って調べてみると、下記の記事にわかりやすくまとめてくれていました。

【Flutter】アプリの動かし方とビルドモード(Debug / Profile / Release)について | ヒヨコ プログラミング(ヒヨプロ)

なるほど、リリースと同様にビルドするけど、デバッグも一部有効になっているモードというわけね。パフォーマンスが重要になるアプリでデバッグしたい時に使う感じなんでしょうね。

一つ勉強になりました。

Build Phases を修正

参考 URL では、Info-Release.plist が追加されている場合がある、となっていたのですが、手元の環境の場合は、デバッグの方が追加されていました。これって、削除した方がいいのか?と思って修正前のものを確認すると、

のように、 Info.plist は含まれていませんでした。それに、

Xcodeエラー覚書 The Copy Bundle Resources build phase contains this target's Info.plist file: Cocoa日曜プログラム日誌 ここぶろ

のような記事があったので、削除しておいた方が無難かな?と考えて、 Info-Release.plist の指示と同様に削除しておきました。

ビルド&実機デバッグ

さて、ここまでできたら、一応設定は完了のはずです。なので、一度 Xcode でビルドして、実機で動かしてみます。すると、今回は最初に出ていたエラーが出なくなりました。

これで、一応解決したようです。

まとめ

Mac と Xcode による開発環境に慣れていないため、ちょっとエラーが出てくると、色々と調べないといけないため、なかなか手間取りますね。

ま、エラーがなくなったので、よしとしましょう。