CodeDom编译EXE嵌入资源调用报ArgumentNullException问题咨询
问题根因
你遇到的ArgumentNullException是因为Assembly.GetManifestResourceStream()返回了null,空流传入BinaryReader触发参数校验报错。核心原因是嵌入资源的实际逻辑名和你拼接的查找名不匹配:
- 你用
Parameters.EmbeddedResources.Add("C:/Users/User1/Music/sample.mp3");写法本身语法合法,但C#编译器处理嵌入资源时,如果没有显式指定逻辑名,会按照编译器默认规则生成资源名,和你假设的命名空间.文件名规则不一致,导致查找失败。 - 你之前遇到的
Properties does not exist in the current context报错属于正常情况:Properties.Resources是Visual Studio给常规项目自动生成的包装类,CodeDom动态编译场景下默认不会生成这个类,你放弃该方案的选择是对的。
修复方案
方案1:显式指定资源逻辑名(推荐)
CompilerParameters.EmbeddedResources.Add支持第二个参数自定义资源逻辑名,直接和你查找用的命名规则对齐即可:
// 如果你调用Extract时不传InternalPath,就指定逻辑名为TestCompiler.Music.mp3 Parameters.EmbeddedResources.Add(@"C:\Users\User1\Music\sample.mp3", "TestCompiler.Music.mp3"); // 如果你要带Resources前缀,就指定逻辑名为TestCompiler.Resources.Music.mp3 // Parameters.EmbeddedResources.Add(@"C:\Users\User1\Music\sample.mp3", "TestCompiler.Resources.Music.mp3");
该方案完全避开默认命名规则的坑,后续查找资源时不会出现匹配问题。
方案2:修正Extract方法,增加校验和调试逻辑
修改方法增加空校验,找不到资源时直接输出当前程序集所有嵌入资源名,不用手动猜规则:
private static void Extract(string NameSpace, string OutputDir, string InternalPath, string ResourceName) { string resourceFullName = NameSpace + "." + (string.IsNullOrEmpty(InternalPath) ? "" : InternalPath + ".") + ResourceName; Assembly assembly = Assembly.GetCallingAssembly(); // 资源不存在时输出所有已嵌入的资源名,方便调试 if (assembly.GetManifestResourceInfo(resourceFullName) == null) { string allEmbeddedResources = string.Join("\n", assembly.GetManifestResourceNames()); throw new InvalidOperationException($"未找到目标资源:{resourceFullName}\n当前程序集已嵌入的所有资源:\n{allEmbeddedResources}"); } using (Stream s = assembly.GetManifestResourceStream(resourceFullName)) using (BinaryReader r = new BinaryReader(s)) // 用Path.Combine拼接路径,避免斜杠错误 using (FileStream fs = new FileStream(Path.Combine(OutputDir, ResourceName), FileMode.OpenOrCreate)) using (BinaryWriter w = new BinaryWriter(fs)) { w.Write(r.ReadBytes((int)s.Length)); } }
如果你不想显式指定逻辑名,运行修改后的方法,从报错信息里复制实际生成的资源名,替换调用Extract时的参数即可。
内容的提问来源于stack exchange,提问作者coderman69
相关产品推荐
相关产品推荐

