我有两个装配。 " patchsrc.exe"和#34; Assembly-CSharp.dll"
我从patchsrc.exe::TXDLLLoader.Program::Main()
获得了所有IL指令
以及来自Assembly-CSharp.dll::Class::Method()
我删除' ret'从第一个代码编码,然后将它们合并为一个函数。
当我尝试保存它时,我明白了:
未处理的类型' System.ArgumentException'发生在Mono.Cecil.dll
其他信息:会员' System.Reflection.Assembly System.Reflection.Assembly ::的LoadFile(System.String)'在另一个模块中声明,需要导入
我正在使用此代码:
var assembly = AssemblyDefinition.ReadAssembly("./game_Data/Managed/Assembly-CSharp.dll");
var assembly_patchsrc = AssemblyDefinition.ReadAssembly("./patchsrc.exe");
Console.WriteLine("searching..");
Collection<Instruction> instrForPatch = new Collection<Instruction>();
foreach (var methodDefinition in from type in assembly_patchsrc.MainModule.Types from methodDefinition in type.GetMethods() where methodDefinition.FullName.Contains("TXDLLLoader.Program::Main()") select methodDefinition)
{
Console.WriteLine("Found some patch instructions!");
var instr_patchsrc = methodDefinition.Body.Instructions;
instr_patchsrc.Remove(instr_patchsrc.Last());
for (var i = 0; i <= instr_patchsrc.Count - 1; i++)
{
instrForPatch.Add(instr_patchsrc[i]);
}
}
Console.ReadLine();
foreach (var instr in from typeDef in assembly.MainModule.Types
from method in typeDef.Methods
where typeDef.Name.Equals("Class") && method.Name.Equals("Method")
select method.Body.Instructions)
{
Collection<Instruction> oldList = new Collection<Instruction>();
for (var i = 0; i<=instr.Count-1; i++)
{
oldList.Add(instr[i]);
}
instr.Clear();
Console.WriteLine($"Begin injecting patch instructions.. [{instrForPatch.Count}]");
foreach (var instruction in instrForPatch)
{
Console.WriteLine($"Adding instruction: [{instruction}]");
instr.Add(instruction);
}
Console.WriteLine($"Begin injecting old instructions.. [{oldList.Count}]");
foreach (var instruction in oldList)
{
Console.WriteLine($"Adding instruction: [{instruction}]");
instr.Add(instruction);
}
Console.WriteLine("patched!");
}
Console.WriteLine("saving asssembly..");
assembly.Write("./game_Data/Managed/Assembly-CSharp_patched.dll");
我如何解决所有问题?
答案 0 :(得分:2)
正如Cecil documentation on importing中所解释的那样,您使用的static Instruction ImportInstruction(Instruction instruction, ModuleDefinition module)
{
object operand = instruction.Operand;
var fieldOperand = operand as FieldReference;
if (fieldOperand != null)
return Instruction.Create(instruction.OpCode, module.Import(fieldOperand));
var methodOperand = operand as MethodReference;
if (methodOperand != null)
return Instruction.Create(instruction.OpCode, module.Import(methodOperand));
var typeOperand = operand as TypeReference;
if (typeOperand != null)
return Instruction.Create(instruction.OpCode, module.Import(typeOperand));
return instruction;
}
成员引用的范围限定为模块。如果要在其他模块中使用引用,则需要先导入它。由于您不知道您在patchsrc中遇到的指令,因此您需要能够导入任何指令的任何操作数。为此,您可以编写辅助方法:
foreach (var instruction in instrForPatch)
{
Console.WriteLine($"Adding instruction: [{instruction}]");
instr.Add(ImportInstruction(instruction, assembly.MainModule));
}
然后在添加patchsrc指令时使用它:
var marker = event.dispatchMarker;
var rootID = ReactNativeTagHandles.getNativeTopRootIDFromNodeID(marker);
var rootTag = ReactNativeTagHandles.rootNodeIDToTag[rootID];