2016-06-26 3 views
1

У меня есть две сборки. «Patchsrc.exe» и «сборочно-CSharp.dll»
я получаю все IL-инструкция от patchsrc.exe::TXDLLLoader.Program::Main()
И все IL-инструкция от Assembly-CSharp.dll::Class::Method()ArgumentException в Mono.Cecil при сохранении сборки

я удалить «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

Mono.Cecil является открытым исходным кодом. Найдите его код на GitHub и отлаживайте его, чтобы узнать, что именно приводит к исключению. –

+0

@LexLi Я не уверен, насколько это важно, сообщение об исключении уже говорит о том, что приводит к исключению. – svick

ответ

2

Как объясняется в Cecil documentation on importing, ссылки на члены, подобные одному, на LoadFile(), которые вы используете, связаны с модулями. Если вы хотите использовать ссылку в другом модуле, вам необходимо сначала импортировать ее. Поскольку вы не знаете, какие инструкции вы встретите в patchsrc, вы должны иметь возможность импортировать любые операнды любой команды. Чтобы сделать это, вы можете написать вспомогательный метод:

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)); 
} 
+0

Большое вам спасибо! – NulledCoder

Смежные вопросы