2016-06-26 3 views
1

J'ai deux assemblages. "Patchsrc.exe" et "Assemblée-CSharp.dll"
je reçois tous les IL-instructions de patchsrc.exe::TXDLLLoader.Program::Main()
Et tous les IL-instructions de Assembly-CSharp.dll::Class::Method()ArgumentException dans Mono.Cecil lors de la sauvegarde de l'assemblage

-je supprimer 'RET' opcode du premier code, puis de les fusionner en une fonction.

Lorsque je tente de le sauver, je reçois ceci:

Une exception non gérée du type 'System.ArgumentException' a eu lieu dans Mono.Cecil.dll

Informations complémentaires: System.Reflection » Membre .assembly System.Reflection.Assembly :: LoadFile (System.String) » est déclaré dans un autre module et doit être importé

J'utilise ce code:

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"); 

Comment puis-je tout résoudre?

+1

Mono.Cecil est open source. Trouver son code sur GitHub et déboguer dedans pour voir ce qui conduit exactement à l'exception. –

+0

@LexLi Je ne sais pas comment cela est pertinent, le message d'exception indique déjà ce qui conduit à l'exception. – svick

Répondre

2

Comme expliqué dans Cecil documentation on importing les références membres comme celle à LoadFile() que vous utilisez sont limitées aux modules. Si vous souhaitez utiliser la référence dans un autre module, vous devez d'abord l'importer. Puisque vous ne savez pas quelles instructions vous allez rencontrer dans patchsrc, vous devez pouvoir importer n'importe quel opérande de n'importe quelle instruction. Pour ce faire, vous pouvez écrire une méthode d'assistance:

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; 
} 

Et utilisez-le lorsque vous ajoutez des instructions de patchsrc:

foreach (var instruction in instrForPatch) 
{ 
    Console.WriteLine($"Adding instruction: [{instruction}]"); 
    instr.Add(ImportInstruction(instruction, assembly.MainModule)); 
} 
+0

Merci beaucoup! – NulledCoder