调用dnlib的ModuleDefMD.Write后程序集属性丢失问题求助
dnlib处理.NET程序集后程序集属性丢失的解决方案
问题现象
使用dnlib修改.NET程序集后,仅[assembly: AssemblyVersion("1.0.0.0")]属性被保留,Assembly Name、Assembly Company等其余程序集属性全部丢失,调用Assembly.GetAssembly().GetName时抛出异常。
可能原因
你在加载模块时指定了CLRRuntimeReaderKind.Mono读取器,该读取器在处理.NET Framework程序集的元数据时,可能存在未正确加载全部程序集自定义属性的兼容性问题。
解决方案
1. 更换读取器类型
将模块创建时的读取器类型改为CLRRuntimeReaderKind.Auto(自动适配运行时),对于.NET Framework程序集,该选项能更准确地加载所有元数据:
var moduleCreationOptions = new ModuleCreationOptions(moduleContext, CLRRuntimeReaderKind.Auto);
2. 调整写入选项
修改ModuleWriterOptions的元数据保留设置,避免因过度保留偏移导致元数据结构异常:
var moduleWriterOptions = new ModuleWriterOptions(moduleDefMD); moduleWriterOptions.MetadataLogger = DummyLogger.NoThrowInstance; // 仅保留必要的签名数据,而非所有偏移 moduleWriterOptions.MetadataOptions.Flags = MetadataFlags.PreserveExtraSignatureData; moduleWriterOptions.Cor20HeaderOptions.Flags = ComImageFlags.ILOnly;
如果需要强制保留所有元数据结构,可直接设置为:
moduleWriterOptions.MetadataOptions.Flags = MetadataFlags.PreserveAll;
3. 排查静态构造函数修改逻辑
暂时注释掉添加静态方法和修改全局静态构造函数的代码,验证是否是该操作触发了元数据丢失:
// 注释此段代码,测试写入后属性是否正常 /* var methodDef = new MethodDefUser(Guid.NewGuid().ToString(), MethodSig.CreateStatic(moduleDefMD.CorLibTypes.Void)); methodDef.IsStatic = true; methodDef.Body = new CilBody(); methodDef.Body.Instructions.Add(new Instruction(OpCodes.Ret)); moduleDefMD.GlobalType.Methods.Add(methodDef); var cctorInstructions = moduleDefMD.GlobalType.FindOrCreateStaticConstructor().Body.Instructions; cctorInstructions.Insert(0, new Instruction(OpCodes.Call, methodDef)); */
若注释后属性保留正常,说明修改静态构造函数时可能破坏了元数据关联,此时可尝试重新构建IL指令,确保元数据完整性。
4. 验证程序集属性加载情况
读取模块后,先检查所有程序集自定义属性是否已正确加载,确认问题出在读取还是写入阶段:
// 输出所有加载的程序集属性 foreach (var attr in moduleDefMD.Assembly.CustomAttributes) { Console.WriteLine($"Loaded attribute: {attr.AttributeType.FullName}"); }
内容的提问来源于stack exchange,提问作者sunnamed
相关产品推荐
相关产品推荐

