はじめに
この記事では、Windows Forms の SaveFileDialog における「OverwritePrompt」プロパティを解説します。既存ファイルへ上書きする際に OS 標準の確認ダイアログを出すかどうかを制御する重要な設定です。基本の振る舞いから、無効化した場合の安全な実装(自前確認)、例外対策まで、初心者にもわかりやすく整理します。
学べること:
・OverwritePrompt の役割と既定値
・OS 標準の上書き確認ダイアログが出るタイミング
・無効化時に必要な「自前の上書き確認」実装パターン
・ダブルプロンプトや競合状態を避けるコツ
説明
OverwritePrompt は、ユーザーが既存ファイル名を指定して「保存」を押したときに、上書き確認ダイアログ(「このファイルは既に存在します。置き換えますか?」等)を表示するかを決めます。
ポイント:
・既定値は true。そのため、通常は OS 標準の確認が出ます。
・true の場合、確認は ShowDialog() の内部で行われ、ユーザーが「いいえ」を選ぶとダイアログは閉じず、ShowDialog() もまだ戻りません。
・false にすると、確認なくパスがそのまま返るため、アプリ側で上書き確認を行うのが安全です(File.Exists で検査して MessageBox 等で確認)。
なお、SaveFileDialog は保存処理そのものは行いません。あくまで「保存先パスの決定」を担当し、実際の書き込みはアプリ側で行う点を押さえておきましょう。
サンプルコード
テキストを入力し、「保存…」ボタンで SaveFileDialog を開く最小アプリです。チェックボックスで OverwritePrompt の有効/無効を切り替え、false の場合は自前で上書き確認を出します。
using System; using System.IO;
using System.Text;
using System.Windows.Forms;
public class MainForm : Form
{
private readonly TextBox _txt = new TextBox();
private readonly Button _btnSave = new Button();
private readonly CheckBox _chkOverwrite = new CheckBox();
public MainForm()
{
Text = "SaveFileDialog: OverwritePrompt デモ";
Width = 560;
Height = 380;
_txt.Multiline = true;
_txt.ScrollBars = ScrollBars.Both;
_txt.Dock = DockStyle.Fill;
_chkOverwrite.Text = "OverwritePrompt を有効にする(既定)";
_chkOverwrite.Checked = true;
_chkOverwrite.AutoSize = true;
_btnSave.Text = "保存...";
_btnSave.AutoSize = true;
_btnSave.Click += OnSaveClick;
var top = new FlowLayoutPanel
{
Dock = DockStyle.Top,
Height = 56,
Padding = new Padding(8),
FlowDirection = FlowDirection.LeftToRight
};
top.Controls.Add(_chkOverwrite);
top.Controls.Add(_btnSave);
Controls.Add(_txt);
Controls.Add(top);
}
private void OnSaveClick(object sender, EventArgs e)
{
using (var sfd = new SaveFileDialog())
{
// 上書き確認の有効/無効(既定は true)
sfd.OverwritePrompt = _chkOverwrite.Checked;
// 最低限の設定
sfd.Title = "ファイルを保存";
sfd.FileName = "memo.txt"; // 提案名
sfd.Filter = "テキストファイル (*.txt)|*.txt|すべてのファイル (*.*)|*.*";
sfd.DefaultExt = "txt";
sfd.AddExtension = true;
sfd.RestoreDirectory = true;
var dr = sfd.ShowDialog(this);
if (dr == DialogResult.OK)
{
var path = sfd.FileName;
// OverwritePrompt を無効にしている場合は、自前で確認する
if (!sfd.OverwritePrompt && File.Exists(path))
{
var overwrite = MessageBox.Show(
"既に存在するファイルです。上書きしますか?\n" + path,
"上書きの確認",
MessageBoxButtons.YesNo,
MessageBoxIcon.Warning,
MessageBoxDefaultButton.Button2);
if (overwrite != DialogResult.Yes)
return; // ユーザーが拒否
}
try
{
// 実際の保存処理(UTF-8 BOMなし)
File.WriteAllText(path, _txt.Text, new UTF8Encoding(false));
MessageBox.Show(
"保存しました:\n" + path,
"保存完了",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show(
"保存に失敗しました。\n" + ex.Message,
"エラー",
MessageBoxButtons.OK,
MessageBoxIcon.Error);
}
}
}
}
— サンプルコードの解説 —
① OverwritePrompt の反映: チェックボックスの状態を sfd.OverwritePrompt にそのまま渡しています。true のとき、既存ファイルを選んで「保存」を押すと OS 標準の確認が表示され、承認されない限り ShowDialog() は戻りません。
② 自前確認の条件: OverwritePrompt を false にした場合のみ、File.Exists(path) で存在判定し、MessageBox で確認しています。これにより二重に確認が出ることを防ぎます(true のときは OS 側に任せる)。
③ 例外対策: 書き込みはパスの権限・ディスク容量・ネットワーク切断などの理由で失敗することがあります。try-catch でユーザーに明確なエラーを返すのが実運用では必須です。
④ 付随設定: DefaultExt と AddExtension で拡張子の付け忘れを防止し、RestoreDirectory でカレントディレクトリの副作用を避けています。
つまづきポイント
二重プロンプト: OverwritePrompt = true のまま自前でも確認を出すと、OS とアプリで確認が二重に発生します。どちらか片方に統一しましょう。
既定値の取り違え: OverwritePrompt の既定は true です。わざわざ false にしたのを忘れて、確認なしで上書きしてしまう事故に注意。
競合状態(TOCTOU): 存在チェックから書き込みまでの間に別プロセスがファイルを変更/削除する可能性があります。確認後でも書き込みは失敗し得るため、try-catch は必須です。
拡張子の扱い: ダイアログ側の確認は「最終的なファイル名」に対して行われます。AddExtension やユーザー入力で拡張子が変わる場合、意図したファイルに上書きしているかをメッセージで明示すると親切です。
ネットワーク/リモート保存: UNC パスや取り外しメディアでは遅延や切断が起きやすいです。完了メッセージだけでなく、保存時間の見通しや保存先の表示でユーザーの不安を減らしましょう。
まとめ
OverwritePrompt は「既存ファイルに上書きする前の一呼吸」を担う安全装置です。基本は true(既定)で OS 標準の確認に任せる。意図があって false にする場合は、File.Exists と MessageBox などで自前の確認を実装し、最後は例外処理で守りを固める。この型を押さえれば、ユーザーのデータを守りながら快適な保存体験を提供できます。


コメント