注入类型与方法时遭遇Parent Does not Exist Error问题求助
排查"Parent Does not Exist Error"并实现方法替换
首先,咱们先拆解你遇到的Parent Does not Exist Error的核心原因,再一步步修正代码:
问题根源分析
- 类型关联缺失:你创建的
TypeDefUser("Simpy")没有设置有效的Parent属性,dnlib要求所有类型必须关联父节点(顶级类的父节点是模块的GlobalType),InjectHelper在注入校验时会因为找不到父节点抛出错误。 - 元数据Token跨模块不兼容:你用当前AppDomain中
typeof(Simpy).MetadataToken去解析另一个模块(moduleDefMD)的类型是错误的——不同模块的元数据Token是独立的,跨模块解析会得到无效的类型定义。 - 注入流程顺序冲突:你手动将目标类型添加到模块后再调用InjectHelper,这和InjectHelper的预期流程不符,它通常会自行处理类型的关联与模块添加操作。
解决方案与修正后的代码
步骤1:修正类型注入逻辑
先从源模块中正确获取Simpy类型,再创建目标类型容器,由InjectHelper完成父节点关联和注入操作。
步骤2:精准替换目标方法
调整指令遍历逻辑,专门查找调用System.Convert.FromBase64String的位置,替换为Simpy.Simp调用。
完整修正代码
// 加载包含Simpy类型的源模块 ModuleDefMD sourceModule = ModuleDefMD.Load(typeof(runtime).Module); // 从源模块直接查找Simpy类型(避免跨模块元数据Token问题) TypeDef sourceSimpyType = sourceModule.Types.First(t => t.Name == "Simpy"); // 目标模块(你需要修改的目标模块实例,替换为你的moduleDef变量) // 创建目标类型容器,指定基类为Object,暂不添加到模块 TypeDef targetSimpyType = new TypeDefUser(null, "Simpy", sourceModule.CorLibTypes.Object.TypeDefOrRef); targetSimpyType.Attributes = TypeAttributes.AutoLayout | TypeAttributes.Class | TypeAttributes.Public; // 执行类型与方法注入,获取注入后的定义集合 IEnumerable<IDnlibDef> injectedDefs = InjectHelper.Inject(sourceSimpyType, targetSimpyType, moduleDef); // 提取注入后的Simp方法 MethodDef simpMethod = (MethodDef)injectedDefs.Single(m => m.Name == "Simp"); // 将方法导入到目标模块(确保调用时的兼容性) var importedSimpMethod = moduleDef.Import(simpMethod); // 遍历目标模块所有方法,替换FromBase64String调用 foreach (TypeDef type in moduleDef.Types) { foreach (MethodDef method in type.Methods) { if (method.Body == null) continue; method.Body.SimplifyBranches(); var instructions = method.Body.Instructions; // 查找调用System.Convert.FromBase64String的指令 for (int i = 0; i < instructions.Count; i++) { Instruction instr = instructions[i]; if (instr.OpCode == OpCodes.Call && instr.Operand is IMethodDefOrRef methodRef) { // 匹配目标方法的完整签名 if (methodRef.FullName == "System.String System.Convert::FromBase64String(System.String)") { // 替换为调用注入后的Simp方法 instr.Operand = importedSimpMethod; // 若Simp方法签名与FromBase64String不一致,需额外调整参数/返回值指令 } } } // 还原方法体的分支结构优化 method.Body.OptimizeBranches(); } }
关键修正点说明
- 正确获取源类型:直接从源模块按名称查找
Simpy类型,彻底避免跨模块元数据Token不兼容的问题。 - 自动关联父节点:创建
TypeDefUser时指定基类,InjectHelper会自动设置Parent为目标模块的GlobalType,解决"Parent Does not Exist"错误。 - 精准替换目标方法:专门匹配
System.Convert.FromBase64String的调用指令,直接替换操作数为注入后的Simp方法,完全贴合你的需求。 - 修复方法体结构:修改指令后调用
OptimizeBranches(),确保方法体的分支逻辑保持正确。
内容的提问来源于stack exchange,提问作者Yung Samzy
相关产品推荐
相关产品推荐

