简体   繁体   中英

Run Mono.Cecil in .NET Core

I ran the HelloWorld console app example from a SO anwser compiled with .NET Core 2 and Mono.Cecil 0.10.0-beta7:

var myHelloWorldApp = AssemblyDefinition.CreateAssembly(
    new AssemblyNameDefinition("HelloWorld", new Version(1, 0, 0, 0)), "HelloWorld", ModuleKind.Console);

var module = myHelloWorldApp.MainModule;

// create the program type and add it to the module
var programType = new TypeDefinition("HelloWorld", "Program",
    Mono.Cecil.TypeAttributes.Class | Mono.Cecil.TypeAttributes.Public, module.TypeSystem.Object);

module.Types.Add(programType);

// add an empty constructor
var ctor = new MethodDefinition(".ctor", Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.HideBySig
    | Mono.Cecil.MethodAttributes.SpecialName | Mono.Cecil.MethodAttributes.RTSpecialName, module.TypeSystem.Void);

// create the constructor's method body
var il = ctor.Body.GetILProcessor();

il.Append(il.Create(OpCodes.Ldarg_0));

// call the base constructor
il.Append(il.Create(OpCodes.Call, module.Import(typeof(object).GetConstructor(Array.Empty<Type>()))));

il.Append(il.Create(OpCodes.Nop));
il.Append(il.Create(OpCodes.Ret));

programType.Methods.Add(ctor);

// define the 'Main' method and add it to 'Program'
var mainMethod = new MethodDefinition("Main",
    Mono.Cecil.MethodAttributes.Public | Mono.Cecil.MethodAttributes.Static, module.TypeSystem.Void);

programType.Methods.Add(mainMethod);

// add the 'args' parameter
var argsParameter = new ParameterDefinition("args",
    Mono.Cecil.ParameterAttributes.None, module.Import(typeof(string[])));

mainMethod.Parameters.Add(argsParameter);

// create the method body
il = mainMethod.Body.GetILProcessor();

il.Append(il.Create(OpCodes.Nop));
il.Append(il.Create(OpCodes.Ldstr, "Hello World"));

var writeLineMethod = il.Create(OpCodes.Call,
    module.Import(typeof(Console).GetMethod("WriteLine", new[] { typeof(string) })));

// call the method
il.Append(writeLineMethod);

il.Append(il.Create(OpCodes.Nop));
il.Append(il.Create(OpCodes.Ret));

// set the entry point and save the module
myHelloWorldApp.EntryPoint = mainMethod;
myHelloWorldApp.Write("HelloWorld.exe");

The above code executes fine when compiling with .NET Framework, but when compiling with .NET Core resulted in the error:

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'System.Console, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' or one of its dependencies. The system cannot find the file specified.

at HelloWorld.Program.Main(String[] args)

I'd like to ask, why can't the HelloWorld app locate the assembly file mscorlib.dll? What should I do to fix it?

I solved this by creating a HelloWorld.runtimeconfig.json at the same folder of HelloWorld.exe and then ran dotnet./HelloWorld.exe . It would print Hello World to the console.

The Json file:

{
  "runtimeOptions": {
    "tfm": "netcoreapp2.0",
    "framework": {
      "name": "Microsoft.NETCore.App",
      "version": "2.0.0"
    }
  }
}

you must be performing the assembly manipulation from within .net classic, ie .net 4.x. so this means when u do typeof(Console) is imports the Console from the full runtime, no from the NET Core runtime

If you use typeof(...) , you are importing types from the current runtime (.NET Core 2). If you want to make a .NET Framework application from .NET Core, you need to import mscorlib from .NET Framework on Windows, or mono, and use the types from it. See my other answer: https://stackoverflow.com/a/73434552/4205390

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM