.NET 8 の .NET MAUI アプリから USB メモリを NTFS / FAT32 にフォーマットしようとしたら「Access Denied」「Cannot open volume for direct access」で失敗する――。原因の多くはコードではなく、Windows のデバイス制御(グループポリシー等)が“書き込み”を止めていることです。本記事では切り分けと現実的な解決策を整理します。
現象:.NET MAUI から USB をフォーマットすると Access Denied になる
Windows 向けの .NET 8 / .NET MAUI アプリで USB メモリを NTFS または FAT32 へフォーマットしたい。しかし、組織のデバイス制御(グループポリシー、Endpoint 管理、セキュリティ製品のデバイス制御など)により USB へのアクセスが制限されており、フォーマット処理が次のようなメッセージで失敗するケースがあります。
- Access Denied / 権限不足(実行ユーザーが管理者でない、または権限が付与されていない)
- Cannot open volume for direct access(ボリュームの排他ロックや raw アクセスができない)
- 管理者(elevated)で実行し、ディスクがロックされていないことを確認せよ系のエラー
さらに「cmd.exe を使いたくない(ポリシーに抵触しそう)」「できればアプリのコードだけで完結したい」「diskpart なら通るのでは?」という相談がセットで出やすいのも特徴です。
結論:USB 書き込み禁止のデバイス制御下では“フォーマットは基本的にできない”
まず押さえるべきポイントは、フォーマットは“ファイルシステムの作成=強い書き込み操作”だということです。通常のファイルコピーよりも低レイヤ(ボリューム管理・ファイルシステム初期化)に踏み込み、Windows は以下のような操作を行います。
- ボリュームを排他ロックする(他プロセスが使っていない状態にする)
- ファイルシステムの初期化やメタデータ作成を行う
- 必要に応じてボリュームのマウント解除・再マウントを行う
このとき、デバイス制御が「リムーバブルへの書き込み禁止」を徹底している環境では、OS がフォーマットに必要な I/O を拒否します。つまり、アプリ側でどれだけ工夫しても、許可されていない書き込みを“コードで回避”することは基本的に成立しません。
現場でよく起きる誤解は次の 2 つです。
- 「cmd.exe を使うから止まる。API を叩けばいけるのでは?」
- 「MAUI アプリだけ許可すれば良いのでは?」
しかし実際には、フォーマットを成立させるには OS が raw/ボリューム管理レベルの書き込みを許可する必要があります。許可されていない場合、実行主体が cmd.exe でも diskpart.exe でも、WMI でも、P/Invoke でも、最終的に OS から拒否されます。
なぜ「アプリだけ許可」では足りないのか:実行主体と“関与プロセス”の罠
「MAUI.exe を許可リストに入れれば、MAUI からの操作は通るはず」と考えがちです。ところが、実装方式によっては実際の処理が別プロセスや別コンポーネントに委譲されます。
代表例として、次のような流れが起きやすいです。
- MAUI アプリがフォーマット要求を出す
- 内部的に OS のフォーマットエンジンや管理コンポーネントが動く
- 環境によってはユーティリティ(diskpart 等)やサービス側コンポーネントが関与する
デバイス制御が「どのプロセスが、どのデバイスへ、どんな操作をしたか」を評価している場合、MAUI.exe を許可しても、関与する別プロセスがブロックされれば結果は同じです。さらに、制御がプロセス単位ではなくデバイス・クラス単位(USB 大分類)や書き込み操作の種類単位で厳格に拒否している場合、許可リストの考え方そのものが通用しません。
Access Denied が起きる“層”を整理する(切り分けの土台)
フォーマット失敗を「MAUI のバグ」「権限不足」と一括りにすると、遠回りになります。どの層で止まっているかを整理すると、対処方針が明確になります。
| 止まる層 | 典型症状 | 何が起きているか | アプリ側でできること |
|---|---|---|---|
| UAC / 管理者権限 | Access Denied、管理者で実行せよ | 管理系 API 実行に必要な権限が不足 | 管理者起動の案内、昇格必須設計 |
| ボリュームの排他ロック | Cannot open volume for direct access / ロックできない | Explorer/AV/インデクサ等がボリュームを掴んでいる | 閉じる誘導、リトライ、前処理(可能な範囲) |
| デバイス制御(書き込み禁止) | 一部操作だけ拒否、フォーマットだけ必ず失敗 | “書き込み”が組織ポリシーで拒否されている | 回避は不可。例外設計・運用見直しが必要 |
| メディア側の保護 | 書き込み保護、属性変更不可 | 物理スイッチ/ファーム/媒体不良など | ユーザーへ確認、媒体交換を提案 |
今回の前提は「デバイス制御ポリシー適用中」なので、最終的な着地点は“例外をどう設計するか”になります。ただし、現場では複合要因(権限 + ロック + ポリシー)が多いので、次章のチェックで詰めていきます。
まず確認すべき前提条件(ここが崩れていると必ず詰まる)
管理者権限(昇格)が必要
USB フォーマットは一般ユーザー権限では通らないことが多く、少なくとも Windows 側では管理者として実行が必要になる場面が頻繁にあります。MAUI アプリでフォーマット機能を提供するなら、次のいずれかは避けて通れません。
- アプリ自体を常に管理者起動にする(運用負荷が高い)
- フォーマットだけ別の昇格プロセス(ヘルパー)に委譲する
- 管理者権限で動くサービスに委譲する(要ポリシー設計)
ボリュームが他プロセスに掴まれていないこと
Explorer でドライブを開いている、ウイルス対策ソフトがスキャンしている、インデクサが回っている、といった状態だと、フォーマットが取るべき排他制御が成立せず、「direct access できない」系のエラーになります。
“対象ドライブの誤選択”を防ぐ UI が必須
フォーマットは破壊的操作です。MAUI アプリに組み込むなら、技術面以前に誤爆防止が最重要です。少なくとも以下の表示は揃え、ユーザーが確信を持って選べる状態にしてください。
- ドライブレター
- ボリュームラベル
- 容量(総容量と空き容量)
- リムーバブル判定(可能なら USB と判定できる情報)
.NET 8 / .NET MAUI での実装パターンと、ポリシー下での現実
「cmd.exe を使わず、コードだけでフォーマットしたい」という要望は自然です。Windows にはいくつかの手段がありますが、どれを選んでも“ポリシーが書き込みを拒否している限り結果は同じ”という前提をまず共有します。
| 方式 | 概要 | メリット | デメリット / 注意点 | デバイス制御下の見込み |
|---|---|---|---|---|
| cmd.exe / format / diskpart 起動 | 外部ユーティリティに任せる | 実装が簡単、動作実績が多い | ポリシー抵触しやすい、監査上嫌われる | ブロックされやすい(例外でも監査対象) |
| WMI(Win32_Volume.Format) | WMI 経由でボリュームの Format を呼ぶ | コード完結、cmd.exe 不要 | 管理者権限が必要になりがち、環境依存 | 原則ブロック(許可されていれば動く) |
| Windows のフォーマット API 呼び出し | OS のフォーマット機能を直接利用 | プロセスを増やさず実装可能 | 低レイヤ、例外処理が難しい | 原則ブロック(許可されていれば動く) |
| 管理者サービスに委譲 | Windows サービスがフォーマットを実施 | 権限と UI を分離できる | 設計が重い、セキュリティ審査が必須 | 例外設計ができれば成立しやすい |
スレッド等で「diskpart なら動いた」というケースが出ることがありますが、これは多くの場合、次のどちらかです。
- 管理者で実行できた(権限要件を満たしただけ)
- ポリシーが diskpart を例外扱いしていた/すり抜けた(制御設計の差)
厳密な制御環境では diskpart も同様にブロックされ得ます。つまり、「diskpart が通った=根本的に回避できる」ではなく、環境依存の結果として捉えるのが安全です。
cmd.exe を使わず“コードだけ”で実行する例(ただしポリシー許可が前提)
ここでは「外部プロセス(cmd.exe / diskpart.exe)を起動しない」という要件を満たしやすい例を紹介します。繰り返しになりますが、デバイス制御が書き込みを禁止している環境では失敗します。このコードは、あくまで「許可されている環境で、アプリからフォーマットを呼ぶ」ための参考です。
管理者起動チェック(MAUI アプリ側)
まず、実行ユーザーが管理者かどうかを判定し、足りない場合はユーザーに明確に伝えます。実運用では「ボタンを押したら失敗」より、事前に不可条件を提示して操作を止めるほうがトラブルが減ります。
#if WINDOWS
using System.Security.Principal;
public static bool IsAdministrator()
{
using var identity = WindowsIdentity.GetCurrent();
var principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
#endif
起動を強制する場合は、Windows アプリのマニフェストで昇格を要求する設計もあります。ただし、常時昇格は運用・監査・UX の面で負担が大きいので、実際には「フォーマット機能だけ昇格ヘルパーに委譲」などを検討することが多いです。
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
WMI の Win32_Volume.Format を呼ぶ例
WMI 経由でフォーマットを呼ぶと、外部コマンド起動を避けやすいです。Windows 限定になるため、.NET MAUI では Windows 条件コンパイルや Platforms/Windows 配下への分離を行ってください。
#if WINDOWS
using System.Management;
public static void FormatVolume(string driveLetter, string fileSystem, string label, bool quickFormat)
{
// driveLetter 例: "E:"
// fileSystem 例: "NTFS", "FAT32", "exFAT"
var query = new SelectQuery("SELECT * FROM Win32_Volume WHERE DriveLetter = '" + driveLetter + "'");
using var searcher = new ManagementObjectSearcher(query);
foreach (ManagementObject volume in searcher.Get())
{
var inParams = volume.GetMethodParameters("Format");
inParams["FileSystem"] = fileSystem;
inParams["QuickFormat"] = quickFormat;
inParams["Label"] = label;
var outParams = volume.InvokeMethod("Format", inParams, null);
var ret = (uint)(outParams?["ReturnValue"] ?? 1u);
if (ret != 0)
{
// ここで ret に応じてメッセージを出し分ける設計にすると運用が楽になります
throw new InvalidOperationException("Format failed. ReturnValue=" + ret);
}
return;
}
throw new InvalidOperationException("Volume not found: " + driveLetter);
}
#endif
この方式でも、デバイス制御により書き込みが拒否されていれば Access Denied になります。また、ボリュームが他プロセスに掴まれている場合も失敗し得ます。よってアプリ設計としては、フォーマット実行前に以下の状態を作ることが重要です。
- 対象ドライブを Explorer で開いていない
- 可能なら常駐系のアクセスが落ち着くまで待つ(挿してすぐ実行しない)
- ユーザーに「抜き差し直後は少し待つ」などのガイドを出す
それでも Access Denied になるときの切り分け(アプリでできる範囲)
「ポリシーで無理」と結論づける前に、現場では“権限”や“ロック”が混ざっていることが多いです。アプリ側で実装できる切り分けポイントを整理します。
書き込み禁止かどうかを“ユーザー操作で”確認する
最も確実で誤解が少ない確認は、対象 USB にテストファイルを作れるかです。
- 小さなテキストファイルを作成できない → 書き込み禁止(ポリシー・媒体保護)が濃厚
- ファイルは作れるがフォーマットだけ失敗 → 管理権限不足、排他ロック、フォーマット特有の制御が濃厚
アプリで実装するなら、フォーマット実行前に「試し書き込み」を行い、失敗したらフォーマットボタンを無効化する、といった UX が有効です。
ポリシー検知のヒント(“変更”ではなく“検出”に留める)
組織の制御は複数方式があり、アプリ単体で完全に判断するのは難しいです。ただし、よく使われる「書き込み禁止」設定は OS 上に痕跡があることが多いため、検知用に参照するのは有効です(勝手に書き換えるのは避け、管理者に委ねます)。
#if WINDOWS
using Microsoft.Win32;
public static bool MightBeWriteProtected()
{
// 代表例: StorageDevicePolicies の WriteProtect
// ※環境によっては別の仕組みで制御されます。あくまでヒントです。
using var key = Registry.LocalMachine.OpenSubKey(
@"SYSTEM\CurrentControlSet\Control\StorageDevicePolicies",
writable: false);
var v = key?.GetValue("WriteProtect");
return (v is int i) && i == 1;
}
#endif
この種の判定は「100% 正しい診断」ではありませんが、ユーザーに「この端末は USB 書き込み禁止の可能性が高いので管理者へ連絡してください」と案内する根拠になります。
エラーメッセージ別の対処表(現場で効く)
| エラー/状況 | 可能性が高い原因 | 優先して試すこと | 最終的な落としどころ |
|---|---|---|---|
| Access Denied(直後に失敗) | 未昇格、または書き込み禁止ポリシー | 管理者起動チェック、試し書き込み | ポリシー例外 or 運用変更 |
| Cannot open volume for direct access | ボリュームが掴まれている、排他ロック不可 | Explorer を閉じる、挿し直して待つ | サービス委譲や手順見直し |
| 「管理者で実行」「ロックされていないことを確認」 | 権限 + ロックが複合 | 昇格 + 事前案内 + リトライ設計 | 例外設計(許可された端末で実行) |
| ファイルコピーも不可 | 書き込み禁止が確定的 | アプリ側で停止し案内 | IT 側で例外ルール設計 |
“USB をブロックしたままフォーマットしたい”を両立させる現実的な方法
要望として多いのが「普段は USB をブロックしたい。でも業務でフォーマットだけは必要」という状態です。ここはアプリのテクニックだけで解決しにくく、デバイス制御ポリシーの設計と運用が主戦場になります。
現実解のパターン
| 方針 | 概要 | メリット | デメリット | 向いている組織 |
|---|---|---|---|---|
| 運用時だけ一時解除 | 申請・承認の上で短時間だけ制御を緩める | 確実、監査に乗せやすい | 手間がかかる | 厳格な統制が必要 |
| 許可デバイスの限定 | 会社支給 USB(特定 ID)だけ書き込み/フォーマット許可 | リスクを抑えつつ業務継続 | 管理台帳が必要 | 資産管理が整っている |
| 許可端末の限定 | フォーマット専用端末(キオスク)でのみ許可 | 端末側で統制しやすい | 場所・運用が固定される | 拠点運用がある |
| 許可プロセスの限定(要審査) | 署名済みの専用ツール/サービスだけ許可する設計 | UX が良い | 審査・保守が重い | 内製基盤が強い |
ポイントは、「ブロックしたまま」=「書き込み禁止のまま」だとフォーマットが矛盾するということです。両立させるには、次のように “何を例外として許可するか” を必ず決める必要があります。
- 誰が(ユーザー/役割)
- どこで(端末/ネットワーク)
- 何に対して(特定 USB/特定クラス)
- 何だけを(フォーマットを含む書き込み操作)
- いつ(常時か一時か)
diskpart を“代替として使う”前に考えるべきこと
「diskpart なら通るかも」という発想は現場で出やすいですが、次の観点で判断してください。
- 通った理由を説明できるか(管理者で実行しただけ、例外設定が入っているだけ、など)
- 監査上の説明ができるか(禁止されている cmd.exe と同列扱いにならないか)
- 運用として再現性があるか(端末が変わると通らない、では業務が破綻)
もし “例外として許可する” 方針なら、場当たり的に diskpart へ寄せるよりも、組織のルールに沿った「許可された実行主体」を設計したほうが長期的にトラブルが減ります。
.NET MAUI アプリ側でできる「失敗させない設計」
ポリシーはアプリ側では変えられません。だからこそ、MAUI アプリ側は「フォーマット実行」よりも、実行前のガードと失敗時の説明に注力するとユーザー価値が上がります。
フォーマットボタンを押す前にやるべきチェック
- 管理者か(足りなければ実行不可として案内)
- 対象がリムーバブルか(固定ディスクを誤爆しない)
- 試し書き込みができるか(書き込み禁止ならここで止める)
- 容量・ラベル・ドライブレターの提示(誤選択防止)
ユーザーに伝えるべきメッセージ例
Access Denied をそのまま表示すると「アプリが壊れている」と受け取られがちです。組織ポリシーが原因になり得る場合は、次のように次アクションが明確な文面にすると問い合わせが減ります。
- 「この端末は USB への書き込みが制限されている可能性があります。管理者に“USB 書き込み/フォーマットの例外許可”を依頼してください。」
- 「管理者として起動してください(右クリック → 管理者として実行)。」
- 「対象ドライブを開いているアプリ(エクスプローラー等)を閉じてから再試行してください。」
ログ設計(“原因がポリシー”を説明できるようにする)
企業環境では「なぜ失敗したか」を説明できることが重要です。最低限、アプリのログとして次を残すと、IT 部門との会話が短くなります。
- 実行日時
- 対象ドライブの情報(レター/容量/ラベル/リムーバブル判定)
- 管理者権限の有無
- 試し書き込みの成否
- 例外内容(例:戻り値、例外メッセージ)
よくある質問
.NET MAUI のコードだけで、デバイス制御ポリシーを回避できますか?
回避は推奨されず、基本的に成立しません。デバイス制御は OS の低レイヤで書き込みを拒否することが多く、アプリの実装方式を変えても最終的に止まります。必要なら、正規の手続きで例外を設計してください。
「cmd.exe は禁止、diskpart は OK」という運用にできますか?
組織のルール次第ですが、長期的には「どのプロセスを許可するか」よりも「誰が、どのデバイスに、どの操作を許可するか」で設計したほうが破綻しにくいです。監査・再現性・端末差を考慮して IT 部門と合意形成してください。
FAT32 でフォーマットできない容量がありますか?
Windows の標準 UI では FAT32 を選べないケースがあります。ただし、ここでの本質は容量制限よりも、デバイス制御下での書き込み禁止です。まずはポリシー上フォーマットが許可される運用を整えることが先決です。
まとめ:Access Denied はアプリの問題ではなく“制御設計の問題”であることが多い
.NET 8(.NET MAUI)から USB を NTFS/FAT32 にフォーマットしたいのに Access Denied になる場合、原因の中心は次の 3 つです。
- 管理者権限がない
- ボリュームが掴まれていて排他アクセスできない
- デバイス制御ポリシーが書き込み(=フォーマット)を拒否している
特に「USB をブロックしたままフォーマットしたい」は、技術というより運用・ポリシー設計の課題です。アプリ側では、事前チェック、誤爆防止 UI、分かりやすい案内、ログ整備を徹底しつつ、IT 部門と連携して例外ルール(誰に/何に/いつ/どこまで許可するか)を定義するのが最短ルートになります。

コメント