【问题标题】:Injecting a an assembly reference /w Mono Cecil does not work注入程序集引用/w Mono Cecil 不起作用
【发布时间】:2021-10-20 18:24:02
【问题描述】:

我目前正在使用 Mono.Cecil 将程序集引用添加到已编译的程序集中。

我正在使用此代码添加参考:

this.tracerReference = this.module.ImportReference(typeof(Tracer).GetMethod("Trace", new Type[]
            {
                typeof(String)
            }));

Tracer 是来自另一个项目的类。完成对已加载程序集的修改后,我会像这样保存它:

var newAssemblyName =
                Path.GetFileNameWithoutExtension(this._assemblyPath) + ".modified" + Path.GetExtension(_assemblyPath);
            var directory = Path.GetDirectoryName(_assemblyPath);
            Console.WriteLine(newAssemblyName);

            module.Write(Path.Join(directory, newAssemblyName));

一旦我尝试运行新的 dll,我就会看到:

$ dotnet instrospect.TestCli.dll                                                                               
Unhandled exception. System.IO.FileNotFoundException: Could not load file or assembly 'instrospect.types, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.

File name: 'instrospect.types, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'
[1]    4555 abort      dotnet instrospect.TestCli.dll

即使有问题的 dll,introspect.typesintrospectTestCli.dll 在同一目录中,它也找不到它。我错过了什么吗?

【问题讨论】:

    标签: c# .net .net-core mono.cecil


    【解决方案1】:

    dotnet core 上的装配探测工作方式不同。

    在我相应地更新 app.deps.json 文件后,以下示例将按预期工作。

    using System;
    using System.IO;
    using System.Linq;
    using Mono.Cecil;
    using Mono.Cecil.Cil;
    
    namespace mod
    {
        class Program
        {
            static void Main(string[] args)
            {
                if (args.Length > 0)
                {
                    DoIt(args[0]);
                }
                else
                {
                    using var assemblyToReference = AssemblyDefinition.ReadAssembly("xxx.dll");                
    
                    var assemblyPath = typeof(Program).Assembly.Location;
                    using var a = AssemblyDefinition.ReadAssembly(assemblyPath);
                    var t = a.MainModule.GetType("mod.Program");
                    var m = t.Methods.Single(m => m.Name == "DoIt");
    
                    var il = m.Body.GetILProcessor();
    
                    m.Body.Instructions.Clear();
                    
                    il.Emit(OpCodes.Ldarg_0);
                    var method = assemblyToReference.MainModule.GetType("Class1").Methods.Single(m => m.Name == "Show");
                    il.Emit(OpCodes.Call, a.MainModule.ImportReference(method));
                    il.Emit(OpCodes.Ret);
    
                    a.Write(assemblyPath + ".new");
                    System.Console.WriteLine($"New assembly saved to {assemblyPath}.new");
    
                    System.Console.WriteLine("Now you need to:");
                    System.Console.WriteLine($"\t1 - Copy xxx.dll to {Path.GetDirectoryName(assemblyPath)}");
                    System.Console.WriteLine($"\t2 - Update {Path.GetDirectoryName(assemblyPath)}/mod.deps.json");
                    System.Console.WriteLine($"\t3 - Delete {assemblyPath}");
                    System.Console.WriteLine($"\t4 - Rename {assemblyPath}.new to {assemblyPath}");
                    System.Console.WriteLine($"\t5 - Run: dotnet {assemblyPath} 'some string'");
                }
            }
    
            static void DoIt(string msg)
            {            
            }
        }
    }
    
    {
        "runtimeTarget": {
          "name": ".NETCoreApp,Version=v5.0",
          "signature": ""
        },
        "compilationOptions": {},
        "targets": {
          ".NETCoreApp,Version=v5.0": {
            "mod/1.0.0": {
              "dependencies": {
                "Mono.Cecil": "0.11.4",
                "xxx": "1.0.0.0"
              },
              "runtime": {
                "mod.dll": {}
              }
            },
            "Mono.Cecil/0.11.4": {
              "runtime": {
                "lib/netstandard2.0/Mono.Cecil.Mdb.dll": {
                  "assemblyVersion": "0.11.4.0",
                  "fileVersion": "0.11.4.0"
                },
                "lib/netstandard2.0/Mono.Cecil.Pdb.dll": {
                  "assemblyVersion": "0.11.4.0",
                  "fileVersion": "0.11.4.0"
                },
                "lib/netstandard2.0/Mono.Cecil.Rocks.dll": {
                  "assemblyVersion": "0.11.4.0",
                  "fileVersion": "0.11.4.0"
                },
                "lib/netstandard2.0/Mono.Cecil.dll": {
                  "assemblyVersion": "0.11.4.0",
                  "fileVersion": "0.11.4.0"
                }
              }
            },
            "xxx/1.0.0.0": {
              "runtime": {
                "xxx.dll": {
                  "assemblyVersion": "1.0.0.0",
                  "fileVersion": "1.0.0.0"
                }
              }
            }
          }
        },
        "libraries": {
          "mod/1.0.0": {
            "type": "project",
            "serviceable": false,
            "sha512": ""
          },
          "Mono.Cecil/0.11.4": {
            "type": "package",
            "serviceable": true,
            "sha512": "sha512-IC1h5g0NeJGHIUgzM1P82ld57knhP0IcQfrYITDPXlNpMYGUrsG5TxuaWTjaeqDNQMBDNZkB8L0rBnwsY6JHuQ==",
            "path": "mono.cecil/0.11.4",
            "hashPath": "mono.cecil.0.11.4.nupkg.sha512"
          },      
          "xxx/1.0.0.0": {
            "type": "reference",
            "serviceable": false,
            "sha512": ""
          }
        }
      }
    

    注意事项:

    1. xxx.dll 是一个简单的程序集,包含一个名为 Class1 的类和一个静态方法 Show(string)
    2. 找出 app.deps.json 文件中所需更改的最简单方法是在项目文件中手动添加依赖项并比较生成的 app.deps.json 文件(我在上面包含了修改后的 deps.json 文件。您只需搜索 xxx 即可看到需要更新的地方)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-19
      • 1970-01-01
      • 2012-08-27
      • 2011-03-01
      • 1970-01-01
      相关资源
      最近更新 更多