An interesting bug with AppDomain.Load ()

I am trying to find a way to compile assemblies at runtime and load them. The main intention is to store them in a database that is not on disk. So I wrote the code, but I saw an interesting situation. Here is my code:

//SumLib
namespace SumLib
{
    public class SumClass
    {
        public static int Sum(int a, int b)
        {
            return a + b;
        }
    }
}


// Console app
class Program
{

    public static void AssemblyLoadEvent(object sender, AssemblyLoadEventArgs args)
    {

        object[] tt = { 3, 6 };
        Type typ = args.LoadedAssembly.GetType("SumLib.SumClass");
        MethodInfo minfo = typ.GetMethod("Sum");
        int x = (int)minfo.Invoke(null, tt);
        Console.WriteLine(x);
    }

    static void Main(string[] args)
    {

        AppDomain apd = AppDomain.CreateDomain("newdomain", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
        apd.AssemblyLoad += new AssemblyLoadEventHandler(AssemblyLoadEvent);

        FileStream fs = new FileStream("Sumlib.dll", FileMode.Open);
        byte[] asbyte = new byte[fs.Length];
        fs.Read(asbyte, 0, asbyte.Length);
        fs.Close();
        fs.Dispose();

//      File.Delete("Sumlib.dll");

        apd.Load(asbyte);

        Console.ReadLine();
    }
}

The code works fine with the delete line, it is commented out if I uncomment it, the application domain loads the assembly, the method AssemblyLoadEvent()starts, I see number 9 on the console, but when the method is completed it apd.Load()gives an error message: “Could not load file or assembly”. which is quite reasonable.

The question is, how AssemblyLoadEvent()does the method run without an assembly file on disk?

- , , appdomain Load()?

+3
3

, [] . , ( AssemblyLoad), .

@Jester Load() . , - :

// Console app 
class Program 
{  
    public class AssemblyLoader : MarshalByRefObject
    {
        public void LoadAndCall(byte[] binary)
        {
            Assembly loadedAssembly = AppDomain.CurrentDomain.Load(binary);
            object[] tt = { 3, 6 };
            Type typ = loadedAssembly.GetType("SumLib.SumClass");
            MethodInfo minfo = typ.GetMethod("Sum", BindingFlags.Static | BindingFlags.Public);
            int x = (int)minfo.Invoke(null, tt);
            Console.WriteLine(x);
        }
    }

    static void Main()
    {
        AppDomain apd = AppDomain.CreateDomain("newdomain", AppDomain.CurrentDomain.Evidence, AppDomain.CurrentDomain.SetupInformation);
        FileStream fs = new FileStream("Sumlib.dll", FileMode.Open);
        byte[] asbyte = new byte[fs.Length];
        fs.Read(asbyte, 0, asbyte.Length);
        fs.Close();
        fs.Dispose();
        File.Delete("Sumlib.dll");    

        AssemblyLoader loader = (AssemblyLoader)apd.CreateInstanceAndUnwrap(typeof(AssemblyLoader).Assembly.FullName, typeof(AssemblyLoader).FullName);
        loader.LoadAndCall(asbyte);
        Console.ReadLine();
      }
}  
+2

" " newdomain ( , ). , . , . , .

:

  at System.AppDomain.Load (System.String assemblyString, System.Security.Policy.Evidence assemblySecurity, Boolean refonly) [0x00000] in <filename unknown>:0
  at System.AppDomain.Load (System.String assemblyString) [0x00000] in <filename unknown>:0
  at (wrapper remoting-invoke-with-check) System.AppDomain:Load (string)
  at System.Reflection.Assembly.Load (System.String assemblyString) [0x00000] in <filename unknown>:0
  at System.UnitySerializationHolder.GetRealObject (StreamingContext context) [0x00000] in <filename unknown>:0
  at System.Runtime.Serialization.ObjectRecord.LoadData (System.Runtime.Serialization.ObjectManager manager, ISurrogateSelector selector, StreamingContext context) [0x00000] in <filename unknown>:0
  at System.Runtime.Serialization.ObjectManager.DoFixups () [0x00000] in <filename unknown>:0
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadNextObject (System.IO.BinaryReader reader) [0x00000] in <filename unknown>:0
  at System.Runtime.Serialization.Formatters.Binary.ObjectReader.ReadObjectGraph (BinaryElement elem, System.IO.BinaryReader reader, Boolean readHeaders, System.Object& result, System.Runtime.Remoting.Messaging.Header[]& headers) [0x00000] in <filename unknown>:0
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.NoCheckDeserialize (System.IO.Stream serializationStream, System.Runtime.Remoting.Messaging.HeaderHandler handler) [0x00000] in <filename unknown>:0
  at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize (System.IO.Stream serializationStream) [0x00000] in <filename unknown>:0
  at System.Runtime.Remoting.RemotingServices.DeserializeCallData (System.Byte[] array) [0x00000] in <filename unknown>:0
  at (wrapper xdomain-invoke) System.AppDomain:Load (byte[])
  at (wrapper remoting-invoke-with-check) System.AppDomain:Load (byte[])
  at Program.Main (System.String[] args) [0x00000] in <filename unknown>:0

: MSDN:

Load , , . Assembly MarshalByRefObject, , , . , , , , .

+6

Why don't you use the Shadow Copy option ? It can help you.

0
source

Source: https://habr.com/ru/post/1786963/


All Articles