2017-10-10 41 views
0

このような多くの同様の質問があります。しかし、彼らはすべて年をとっており、今日は仕事をしていません(それ以上ですか?)。C#アセンブリをappdomainに動的にロード/アンロードする

これは私の質問です: 私は、メモリにC#アセンブリをロードし、使用したいインターフェイスに一致するタイプが含まれているかどうかを調べたいと思います。アセンブリにこのクラスの種類が含まれている場合、私は参照し、私の主なアプリケーションで使用します。そうでない場合は、dllをアンロードしてから、メインアプリケーションから、またはアプリケーションの実行中に手動でファイルを削除することができます。

私の最初の実装は、単純にappdomainのアプローチを排除しましたが、(アセンブリファイルを削除または置換することなく)機能しました。次に、さまざまな例で説明したようにアセンブリをロードしようとしました。しかし、私はディスクから不要なアセンブリファイルを削除することはできませんでした。

アプリケーションで参照されたときや、何か間違っているときに、アセンブリをアンロードして削除することはできません。 これは私が最後にしようとしたものです:

using System; 
using System.Diagnostics; 
using System.IO; 
using System.Reflection; 
using System.Runtime.CompilerServices; 
using System.Windows.Forms; 
using ESTLogViewer_V2.Formulare; 
using Parent; 
namespace ESTLogViewer_V2 
{ 
    static class Program 
    { 
     //<summary> 
     //Der Haupteinstiegspunkt für die Anwendung. 
     //</summary> 
     [STAThread] 
     static void Main() 
     { 
      LoadTest.Haupt(null); 
     } 
    } 
} 
namespace Parent 
{ 
    public class Constants 
    { 
     // adjust 
     public const string LIB_PATH = @"e:\PRJDOTNET4\ESTLogViewer V2\Plugins\LogFiles_Plugin.dll"; 
    } 

    public interface ILoader 
    { 
     string Execute(); 
    } 

    public class Loader : MarshalByRefObject, ILoader 
    { 
     public string Execute() 
     { 
      var assembly = Assembly.LoadFile(Constants.LIB_PATH); 
      foreach (var t in assembly.GetTypes()) 
      { 
       Debug.WriteLine(t.FullName); 

      } 
      return assembly.FullName; 
     } 
    } 

    class LoadTest 
    { 
     public static void Haupt(string[] args) 
     { 
      var domain = AppDomain.CreateDomain("child"); 
      var loader = (ILoader)domain.CreateInstanceAndUnwrap(typeof(Loader).Assembly.FullName, typeof(Loader).FullName); 
      Console.Out.WriteLine(loader.Execute()); 
      AppDomain.Unload(domain); 
      domain = null; 
      File.Delete(Constants.LIB_PATH); 
     } 
    } 
} 

ので、このコードはFile.Delete声明まで動作します。私はアセンブリファイルを削除できませんでした理由を見つけることを試みた - この質問を書きながら、私はいくつかのより多くのテストをしました、今

LogFiles_Plugin.clsSchritLogDateiSplitter 
LogFiles_Plugin.clsLogFileMeldDateiSplitter 
LogFiles_Plugin.clsLogFileMeldDateiSplitterNG 
LogFiles_Plugin.clsAuftragsAnalyseSplitter 
LogFiles_Plugin.clsAuftrag 
LogFiles_Plugin.clsS_R_SignalSplitter 
LogFiles_Plugin.clsLogFileGVMeldDateiSplitter 
LogFiles_Plugin.clsLogFileGVTeleSplitter 
LogFiles_Plugin.clsLogFileGVTeleSplitter+spalte 
<PrivateImplementationDetails>{37CEBF0C-E73A-4FE7-B152-9A858E6C176D} 
<PrivateImplementationDetails>{37CEBF0C-E73A-4FE7-B152-9A858E6C176D}+__StaticArrayInitTypeSize=6256 
"ESTLogViewer V2.exe" (Verwaltet (v4.0.30319)): "C:\Windows\Microsoft.Net\assembly\GAC_MSIL\mscorlib.resources\v4.0_4.0.0.0_de_b77a5c561934e089\mscorlib.resources.dll" geladen 
Eine Ausnahme (erste Chance) des Typs "System.UnauthorizedAccessException" ist in mscorlib.dll aufgetreten. 

:しかし、それは例外をスローします。私は、それがビジュアルスタジオのリモートデバッガによってロックされていることを知りました。

したがって、2番目の質問は、リモートのデバッガでファイルをロックしないようにする方法です。

答えて

2

私は、Assembly.LoadFile(...)が、AppDomainをアンロードする時点を超えてもファイルをロックすることがわかりました。

私のソリューションは、メモリにバイトをし、その後のAppDomainにロード第1のアセンブリをロードすることです:

var assemblyBytes = System.IO.File.ReadAllBytes("myassembly.dll"); 
var assembly = System.Reflection.Assembly.Load(assemblyBytes); 

ファイルがロックされることはありません、あなたはそれを削除することができますこの方法、など

同様の質問hereにはより良い答えがあります。

+0

こんにちは@John、私は私の例のコードをあなたのコードに置き換えました。 これは、「appdomain」 - 接近のソリューションです。しかし、appdomainを使わなくても動作するはずです。 –

+0

@WolfgangRoth両方とも動作するはずですが、[リンクされた回答](https://stackoverflow.com/a/18935973/3181933)のように、アセンブリがロードされてからアンロードすることはできませんそれはAppDomainにあります。 [MSDN同意](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/assemblies-gac/how-to-load-and-unload-assemblies) – john

+0

私はまだしていないアセンブリの複数の負荷の影響を調べます。しかし、アセンブリロードの私の主な考えは、ユーザーが交換できる私のコードにプラグインを実装できるようにすることでした。また、ユーザがプラグインのリストを更新するたびに、新しいものを追加し、古いものをユーザに示されたリストから削除する必要があります - 実装上のみ異なるアセンブリを置き換えることはできません他のものは同じ名前空間と名前を持っています...明日これを試してみましょう。 –

関連する問題