This project allows you to run .NET executables inside of C#. Discord server: http://discord.gg/SeDrYk79W8
Yes, it will. However, only a limited subset of .NET Features are working.
- if/while/for statements
- Console.Write/Writeline
- Classes
- Fields
- sbyte/byte/ushort/short/int/uint/long/ulong/float/double
- Adding/Subtracting/Multiplying/Dividing/Remainder
- Bitwise Operations (and, or, xor, not, shift left, shift right)
- string.Length
- Loading separate DLLS
- Actions
- Basic generic support
- Really basic reflection
- Sub-classes
- Arrays
Set the DotNetParserRunner or TesterKernel project as the startup project in Visual Studio and click on Run.
First you need to create an instance of DotNetFile
and pass the byte array with the contents of your C# executable. Starting from some .NET core version, the EXE file was made into a stub which just runs dotnet app.dll
. You need to use that dll file for it to work.
var fl = new DotNetFile(@"c:\app.dll");
You can access all of the classes from the Types property in the fl
variable.
Next, create an instance of DotNetClr
. This runs the .NET code.
var clr = new DotNetClr(fl, @"c:\framework\");
C:\framework
points to a folder where a basic corlib is made. You can find one under the releases.
RegisterResolveCallBack is used to load dlls such as System.Private.Corlib. You can run the Start method to begin executing the code.
clr.RegisterResolveCallBack(callback);
clr.Start();
Example of the callback:
private static byte[] AssemblyCallback(string dll)
{
if(dll == "System.Private.CoreLib")
{
return File.ReadAllBytes("framework/System.Private.CoreLib.dll");
}
else
{
return null;
}
}
You can register an "internal" method which can be called from your application which you want to run.
clr.RegisterCustomInternalMethod("TestsComplete", TestsComplete);
private static void TestsComplete(MethodArgStack[] Stack, ref MethodArgStack returnValue, DotNetMethod method)
{
Console.WriteLine("All Tests Completed.");
}
Inside of the function, the Stack variable represents all of the parameters. returnValue represents the return value of the internal method. Ignore it if the return type is void.
To invoke this newly created method, add this code:
TestsComplete();
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern void TestsComplete();
clr.RegisterCustomInternalMethod("TestsRxObject", TestRxObject);
Now the method:
private static void TestRxObject(MethodArgStack[] Stack, ref MethodArgStack returnValue, DotNetMethod method)
{
var cctor = m.GetMethod("DotNetparserTester", "TestObject", ".ctor");
if (cctor == null)
throw new NullReferenceException();
var s = new CustomList<MethodArgStack>();
s.Add(MethodArgStack.String("value"));
returnValue = clr.CreateObject(cctor, s);
}
First we get the constructor method (normally named .ctor
). Then we build the list of parameters and call clr.CreateObject();
public class TestObject
{
public string TestProperty;
public TestObject(string prop)
{
TestProperty = prop;
}
}
[MethodImpl(MethodImplOptions.InternalCall)]
public static extern TestObject TestsRxObject();
var m = TestsRxObject();