保存程序集

时间:2016-06-26 12:26:56

标签: c# dll mono mono.cecil

我有两个装配。 " patchsrc.exe"和#34; Assembly-CSharp.dll"
我从patchsrc.exe::TXDLLLoader.Program::Main()获得了所有IL指令 以及来自Assembly-CSharp.dll::Class::Method()

的所有IL指令

我删除' 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");

我如何解决所有问题?

1 个答案:

答案 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];