user.configが崩壊
対象
- ApplicationSettingsを使用している
- 突然のException on System.Configuration
原因
アプリケーションの不正終了や、不正セクタのせいで、%LocalAppData%\CompanyName\Assembly_Url_sha256\user.configが崩壊する。
対策
Application.Run()前に、CheckConfiguration()をコールする。
formのコンストラクタで処理をさせてもよさげ。
.net - C# - User Settings broken - Stack Overflow (英語)
以下の宣言は忘れずに。参照設定へSystem.Configurationの追加を忘れずに。
using System.Configuration; using System.IO; using System.Threading;
コードは以下の通り。
/// <summary> /// 設定を確認する /// </summary> /// <exception cref="UnauthorizedAccessException">呼び出し元に、必要なアクセス許可がありません。またはpath がディレクトリです。またはpath によって、読み取り専用のファイルが指定されました。</exception> /// <returns>true:設定ファイルが削除された/false:通常</returns> static public bool CheckConfiguration() { try { ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal); return false; } catch (ConfigurationErrorsException ex) { var filename = ex.Filename; if (string.IsNullOrEmpty(filename)) filename = (ex.InnerException as ConfigurationErrorsException)?.Filename; return DeleteWait(filename, 10); } } /// <summary> /// ファイルが削除するまで待機する /// </summary> /// <param name="filename">ファイル名</param> /// <param name="retry">リトライ回数</param> /// <exception cref="UnauthorizedAccessException">呼び出し元に、必要なアクセス許可がありません。またはpath がディレクトリです。またはpath によって、読み取り専用のファイルが指定されました。</exception> /// <returns>削除有無</returns> static bool DeleteWait(string filename, int retry) { if (string.IsNullOrEmpty(filename) || !File.Exists(filename)) return false; for (var i = 0; i < retry; i++) { try { if (File.Exists(filename)) File.Delete(filename); using (var watcher = new FileSystemWatcher(Path.GetDirectoryName(filename), Path.GetFileName(filename))) { if (File.Exists(filename)) watcher.WaitForChanged(WatcherChangeTypes.Deleted); } return true; } catch (IOException) { } Thread.Sleep(1000); } return false; }
参考文献
- アプリケーション設定アーキテクチャ | Microsoft Docs
- アプリケーションの設定の管理 (.NET)
- 2012-07-08
- Microsoft のテクニカル ドキュメントの以前のバージョン | Microsoft Docs
- hash値の記載がsha1となっているが、現在ではsha256。OneClickInstallerを使用していない場合はexeまでのフルパスで生成されるらしい。