如何在新的 AppDomain 中远程加载 .NET DLL



我绑定创建简单的程序控制台应用程序C# .NET 4.0以远程加载DLL文件。我的代码在本地计算机上加载 dll 时按预期工作,但在尝试远程加载时遇到了解决 dll 的问题。我不知道如何处理这个问题,因为我找不到任何远程加载 dll 的代码示例。

我得到的错误如下。

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:ProjectsLoadDllRemotelyLoadDllRemo
telyProgram.cs:line 102
Unhandled Exception: System.NullReferenceException: Object reference not set to
an instance of an object.
   at LoadDllRemotely.Program.LoadRemotely() in C:ProjectsLoadDllRemotelyLoad
DllRemotelyProgram.cs:line 74
   at LoadDllRemotely.Program.Main(String[] args) in C:ProjectsLoadDllRemotely
LoadDllRemotelyProgram.cs:line 28
Press any key to continue . . .

这是我使用新的应用程序域远程加载dll的实现

using System;
using System.IO;
using System.Reflection;
using ZupZip.Lib.Interfaces;
namespace LoadDllRemotely
{
    public class Program
    {
        private const string ASSEMBLY_PATH =
                        @"C:ProjectsLoadDllRemotelyZupZip.LibbinDebugZupZip.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;
            }
        }
    }
}

我还将此源代码添加到Bitbuckget上的开源中

在此处输入链接说明

已修复只需将此配置添加到 App.Config 即可在完全信任环境中运行

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

我也在

https://bitbucket.org/theeranitp/loaddllremotely

相关内容

  • 没有找到相关文章

最新更新