6

そのため、最近、アプリケーション(または実行可能ファイル、あなたがそれを何と呼んでも)が、実行可能ファイルのフォルダー内にまったく見つからないアセンブリをロードおよびアンロードできる必要があるプロジェクトに取り組んでいます。(別のドライブの場合もあります)

例として、アプリケーションをD:\AAA\theAppFolderに配置し、DLL ファイルのアセンブリをC:\BBB\Assembliesに配置できるようにしたいと考えています。

徹底的に調べたところ、 AppDomainは自分自身とアタッチされたアセンブリをアンロードできることがわかったので、試してみようと思いましたが、数時間試行した後に問題があるようです: AppDomains は、アプリケーションベース。

AppDomain のドキュメンタリー (および私自身の経験) によると、 PrivateBinPath を ApplicationBase の外に設定することはできません。また、アプリケーションが存在するドライブの外に ApplicationBase を設定すると (AppDomainSetup を介して)、System.IO.FileNotFoundExceptionを取得できません。アプリケーション自体を見つけます。

そのため、AssemblyResolve ResolveEventHandler を使用して MarhsalByRefObject 継承クラスを使用してアセンブリを取得しようとするフェーズに到達することさえできません...

ここに、私が現在試みていることに関連するコードのスニペットをいくつか示します

    internal class RemoteDomain : MarshalByRefObject
    {
        public override object InitializeLifetimeService() //there's apparently an error for marshalbyref objects where they get removed after a while without this
        {
            return null;
        }
        public Assembly GetAssembly(byte[] assembly)
        {
            try
            {
                return Assembly.Load(assembly);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return null;
        }
        public Assembly GetAssembly(string filepath)
        {
            try
            {
                return Assembly.LoadFrom(filepath);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
            }
            return null;
        }
    }

    public static Assembly LoadAssembly(string modName, BinBuffer bb)
    {
        string assembly = pathDirTemp+"/"+modName+".dll";
        File.WriteAllBytes(assembly, bb.ReadBytes(bb.BytesLeft()));
        RemoteDomain loader = (RemoteDomain)modsDomain.CreateInstanceAndUnwrap(typeof(RemoteDomain).Assembly.FullName, typeof(RemoteDomain).FullName);
        return loader.GetAssembly(assembly);
    }

できる限り具体的に言うと、アプリケーションのベースフォルダー内にないアセンブリをロードするために、アンロード可能な AppDomain を取得する方法はありますか?

4

2 に答える 2

7

それぞれAppDomainに独自のベース ディレクトリがあり、メイン アプリケーションのベース ディレクトリによってまったく制約されません (アプリケーションのメイン AppDomain でない限り)。したがって、AppDomains を使用して目的を達成できます。

あなたのアプローチが機能しない理由は、AppDomains 間で Assembly オブジェクトを渡しているためです。いずれかのメソッドを呼び出すとGetAssembly、アセンブリは子 AppDomain に読み込まれますが、メソッドが戻ると、メインの AppDomain もアセンブリを読み込もうとします。もちろん、アセンブリはメインの AppDomains のベース dirプライベート パス、またはGACにないため、解決されません。

したがって、一般に、の間に渡したり、オブジェクトを渡しTypeたりしないでください。AssemblyAppDomains

アセンブリをメインの AppDomain に漏らさずにロードする簡単な方法は、この回答にあります。

もちろん、アプリケーションを子 AppDomain にロードされたアセンブリで動作させるにはMarshalByRefObject、AppDomain 間のアクセス ポイントとなる派生クラスを作成する必要があります。

于 2013-10-11T10:47:19.063 に答える