C# WPF程序缺失同目录.config无法运行,配置位置异常求助
原因分析
- 项目配置依赖变更:用Visual Studio自带的
Settings.settings创建配置项时,默认会生成app.exe.config,里面包含配置节声明和默认值。以前的项目可能没显式生成这个文件,或者Costura.Fody的处理逻辑不同,现在构建时强制生成了这个依赖文件。 - Costura.Fody的局限:它只负责嵌入依赖DLL,不会自动处理
app.exe.config。程序启动时找不到这个文件,.NET配置系统会抛出未捕获异常,导致WPF程序无声崩溃。 - Settings加载逻辑:访问
Settings.Default时,.NET会先读取同目录的app.exe.config获取基础配置,再加载AppData里的user.config。缺少前者会直接导致配置系统初始化失败,程序启动卡死。
恢复方法
方法1:把app.exe.config嵌入到exe中
- 编辑项目的
.csproj文件,将App.config的生成操作改为Embedded Resource:<ItemGroup> <EmbeddedResource Include="App.config"> <LogicalName>$(TargetName).exe.config</LogicalName> </EmbeddedResource> </ItemGroup> - 添加启动加载代码,从嵌入资源中提取配置到临时目录,让.NET能读取到:
using System; using System.IO; using System.Reflection; using System.Windows; namespace YourAppNamespace { public static class ConfigBootstrapper { [STAThread] public static void Main() { var configName = $"{Assembly.GetExecutingAssembly().GetName().Name}.exe.config"; using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(configName)) { if (resourceStream != null) { var tempConfigPath = Path.Combine(Path.GetTempPath(), configName); using (var fileStream = new FileStream(tempConfigPath, FileMode.Create, FileAccess.Write)) { resourceStream.CopyTo(fileStream); } AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", tempConfigPath); } } // 启动WPF应用 var app = new App(); app.InitializeComponent(); app.Run(); } } } - 在项目属性里,把启动对象改为这个
ConfigBootstrapper.Main方法。
方法2:自定义配置类,彻底摆脱外部config依赖
放弃自动生成的Settings.settings,自己写配置类直接读写AppData目录的user.config:
using System; using System.IO; using System.Xml.Serialization; using System.Windows; public class CustomAppSettings { public string aword { get; set; } = "默认值"; // 可以添加窗口位置等其他配置项 public double WindowLeft { get; set; } public double WindowTop { get; set; } private static string GetConfigFilePath() { var localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); var appConfigDir = Path.Combine(localAppData, "YourAppName", "1.0.0.0"); // 替换成你的应用名和版本 Directory.CreateDirectory(appConfigDir); return Path.Combine(appConfigDir, "user.config"); } public static CustomAppSettings LoadSettings() { var configPath = GetConfigFilePath(); if (!File.Exists(configPath)) return new CustomAppSettings(); var serializer = new XmlSerializer(typeof(CustomAppSettings)); using (var stream = new FileStream(configPath, FileMode.Open)) return (CustomAppSettings)serializer.Deserialize(stream); } public void SaveSettings() { var configPath = GetConfigFilePath(); var serializer = new XmlSerializer(typeof(CustomAppSettings)); using (var stream = new FileStream(configPath, FileMode.Create)) serializer.Serialize(stream, this); } }
然后在窗口中使用这个类:
private CustomAppSettings _appSettings; private void loaded(object sender, RoutedEventArgs e) { _appSettings = CustomAppSettings.LoadSettings(); tbx.Text = _appSettings.aword; } private void Clic_Apply(object sender, RoutedEventArgs e) { _appSettings.aword = tbx.Text; _appSettings.SaveSettings(); }
方法3:修改Settings生成逻辑(不推荐)
打开Settings.settings设计器,把所有配置项的Scope改为User,然后编辑.csproj文件,移除自动生成config的相关节点:
<!-- 注释或删除以下内容 --> <!-- <None Include="App.config" /> --> <!-- <None Include="Settings.settings"> <Generator>SettingsSingleFileGenerator</Generator> <LastGenOutput>Settings.Designer.cs</LastGenOutput> </None> -->
这种方式容易在重新生成Settings时被覆盖,所以不推荐使用。
内容的提问来源于stack exchange,提问作者Iliana
相关产品推荐
相关产品推荐

