C#从.resx读取嵌入资源时resourceStream返回null的问题排查
将若干现有配置文件添加至.resx资源文件中,编写了以下代码从资源文件读取内容并写入Settings.settings配置的目标文件夹,但代码中resourceStream变量始终返回null。已确认.resx文件的Build action设置为Embedded Resource,且GetManifestResourceStream()方法中的命名空间无误,同时提供了相关属性截图及dotPeek截图,寻求问题原因。
代码如下:
using (var resourceStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Fs.ExtendedImporter.Application.Configuration.SampleConfigFiles.ExampleFiles.resx")) { if (resourceStream != null) { using (var resourceReader = new ResourceReader(resourceStream)) { foreach (DictionaryEntry resource in resourceReader) { string resourceName = (string)resource.Key; byte[] resourceData = (byte[])resource.Value; string destinationFile = Path.Combine(Settings.Default.ApplicationConfiguration, resourceName); if (!File.Exists(destinationFile)) { File.WriteAllBytes(destinationFile, resourceData); } } } } else { Logger.Log.Error("Resource file not found."); } }
验证资源的实际嵌入名称
.NET嵌入资源的名称可能和预期存在差异(比如大小写、路径拼接规则)。可以在代码中临时添加一段逻辑,输出程序集内所有嵌入资源的名称,对比你使用的名称是否一致:foreach (var resourceName in Assembly.GetExecutingAssembly().GetManifestResourceNames()) { Logger.Log.Info(resourceName); }根据输出的实际名称修正
GetManifestResourceStream()的参数即可。检查.resx的Custom Tool设置
如果.resx文件的Custom Tool设置为ResXFileCodeGenerator,会自动生成对应的.Designer.cs文件。此时推荐直接通过生成的设计类访问资源,而不是手动读取.resx流,比如:// 假设生成的类为ExampleFiles byte[] resourceData = ExampleFiles.ResourceName;这种方式更可靠,也避免了手动拼接资源名称的错误。
确认资源确实被嵌入程序集
用dotPeek重新检查编译后的程序集,查看Embedded Resources节点下是否存在目标.resx文件或对应的资源项。如果不存在,可能是文件被排除在项目编译范围外,或者Build Action设置未生效,可尝试重新设置Build Action并清理重建项目。注意大小写匹配
.NET的资源名称是大小写敏感的,即使Windows文件系统不区分大小写,嵌入后的资源名称仍严格区分。确保你传入GetManifestResourceStream()的名称和实际嵌入名称的大小写完全一致。核对命名空间与路径的拼接规则
嵌入资源的名称规则为:程序集默认命名空间 + 文件所在文件夹路径(用点分隔) + 文件名。如果项目的默认命名空间曾修改过,或者文件夹的命名空间未继承项目默认值,可能导致名称拼接错误。可通过项目属性确认默认命名空间,再结合文件路径重新推导资源名称。
内容的提问来源于stack exchange,提问作者Nafisian Castle

