How to load .NET DLL remotely within new AppDomain

2

I tied to create simple program Console App C# .NET 4.0 to load DLL file remotely. My code works as expected on load dll that on the local computer but I got problem resolve dll when trying to load remotely. I have no idea to handle this since I can't find any code example that load dll remotely.

The error I got as following.

Could not load file or assembly 'http://codesanook.cloudapp.net/dll/ZupZip.Lib.I
nterfaces.dll' or one of its dependencies. Operation is not supported. (Exceptio
n from HRESULT: 0x80131515)
   at System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String cod
eBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark&
stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntro
spection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.nLoad(AssemblyName fileName, String code
Base, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& s
tackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntros
pection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName as
semblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMar
k& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIn
trospection, Boolean suppressSecurityChecks)
   at System.Reflection.RuntimeAssembly.InternalLoadFrom(String assemblyFile, Ev
idence securityEvidence, Byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm,
Boolean forIntrospection, Boolean suppressSecurityChecks, StackCrawlMark& stackM
ark)
   at System.Reflection.Assembly.LoadFrom(String assemblyFile)
   at LoadDllRemotely.Proxy.GetObject[T](String assemblyPath, String fullTypeNam
e, String[] referencedAssembliesPath) in C:\Projects\LoadDllRemotely\LoadDllRemo
tely\Program.cs:line 102

Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.
   at LoadDllRemotely.Program.LoadRemotely() in C:\Projects\LoadDllRemotely\Load
DllRemotely\Program.cs:line 74
   at LoadDllRemotely.Program.Main(String[] args) in C:\Projects\LoadDllRemotely
\LoadDllRemotely\Program.cs:line 28
Press any key to continue . . .

This is my implementation that load dll remotely with new AppDomain

using System;
using System.IO;
using System.Reflection;
using ZupZip.Lib.Interfaces;

namespace LoadDllRemotely
{
    public class Program
    {
        private const string ASSEMBLY_PATH =
                        @"C:\Projects\LoadDllRemotely\ZupZip.Lib\bin\Debug\ZupZip.Lib.dll";
        private const string ASSEMBLY_URL =
                        @"http://codesanook.cloudapp.net/dll/ZupZip.Lib.dll";

        private const string REFERENCED_ASSEMBLY3_URL =
                @"http://codesanook.cloudapp.net/dll/ZupZip.Lib.Interfaces.dll";

        private const string REFERENCED_ASSEMBLY2_URL =
                @"http://codesanook.cloudapp.net/dll/system.core.dll";


        private const string REFERENCED_ASSEMBLY1_URL =
                @"http://codesanook.cloudapp.net/dll/mscorlib.dll";

        public static void Main(string[] args)
        {
            //LoadLocally();
            LoadRemotely();
        }

        public static void appDomain_DomainUnload(object sender, EventArgs e)
        {
            Console.WriteLine("domain loaded sender: {0}",
                sender.GetType().FullName);
        }


        public static void LoadLocally()
        {
            var appDomain = AppDomain.CreateDomain("dynamicDll");
            appDomain.DomainUnload += new EventHandler(appDomain_DomainUnload);
            var proxy = (Proxy)appDomain.CreateInstanceAndUnwrap(
                typeof(Proxy).Assembly.FullName,
                typeof(Proxy).FullName);

            var calculator = proxy.GetObject<IGradeCalculator>(
                ASSEMBLY_PATH,
                "ZupZip.Lib.GradeCalculator");
            var score = 80;
            Console.WriteLine("you got grad: {0} from score: {1}", calculator.GetGradeForScore(score), score);

            AppDomain.Unload(appDomain);

            File.Delete(ASSEMBLY_PATH);//you can delete referece dll after remove 
        }


        public static void LoadRemotely()
        {
            //app domain setup 
            //load as byte array
            var appDomain = AppDomain.CreateDomain("dynamicDll");
            appDomain.DomainUnload += new EventHandler(appDomain_DomainUnload);

            var proxy = (Proxy)appDomain.CreateInstanceAndUnwrap(
                typeof(Proxy).Assembly.FullName,
                typeof(Proxy).FullName);

            var calculator = proxy.GetObject<IGradeCalculator>(
                ASSEMBLY_URL,
                "ZupZip.Lib.GradeCalculator",
                REFERENCED_ASSEMBLY3_URL);
            var score = 80;
            Console.WriteLine("you got grad: {0} from score: {1}", calculator.GetGradeForScore(score), score);

            AppDomain.Unload(appDomain);

        }

    }

    public class Proxy : MarshalByRefObject
    {
        public T GetObject<T>(
            string assemblyPath,
            string fullTypeName,
            params string[] referencedAssembliesPath) where T : class
        {
            try
            {
                //find reference
                var assemblyToLoad = Assembly.ReflectionOnlyLoadFrom(assemblyPath);
                AssemblyName[] referencedAssemblies = assemblyToLoad.GetReferencedAssemblies();
                //foreach (var referencedAssembly in referencedAssemblies)
                //{
                //    Console.WriteLine("referenceAssemblyName: {0}", referencedAssembly.Name);
                //    Assembly.Load(referencedAssembly.Name);
                //}
                //solve reference assembly
                foreach (var referencedAssemblyPath in referencedAssembliesPath)
                {
                    Assembly.LoadFrom(referencedAssemblyPath);
                }

                //this dll will load in new domain
                var assembly = Assembly.LoadFrom(assemblyPath);
                var type = assembly.GetType(fullTypeName);
                var obj = (T)Activator.CreateInstance(type);
                return obj;
            }
            catch (Exception ex)
            {
                // throw new InvalidOperationException(ex);
                Console.WriteLine(ex.Message);
                Console.WriteLine(ex.StackTrace);
                return null;
            }
        }

    }

}

I also add this source code to my open source on Bitbuckget

enter link description here

c#
dll
appdomain
.net-remoting
asked on Stack Overflow Jan 14, 2014 by theeranitp • edited May 28, 2016 by orad

1 Answer

1

Fixed just add this configuration to App.Config to run in full trust

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <runtime>
        <loadFromRemoteSources enabled="true"/>
    </runtime>
</configuration>

and I also update this code at

https://bitbucket.org/theeranitp/loaddllremotely

answered on Stack Overflow Jan 15, 2014 by theeranitp

User contributions licensed under CC BY-SA 3.0