2011-08-07 9 views
5

私はサードパーティのプログラムに含まれているいくつかのDLLに応じてプログラムを作っています。私はこれらのDLLを自分で配布することはできません。私のプログラムが動作するには、サードパーティのプログラムがインストールされている必要があります。他の場所からのDLL参照

どのようにこれらのDLLへの参照を作成できますか?私は、プログラムによって設定されたレジストリキーを通して、それらの正確な場所を知っています。

Project-> Referencesでファイルを追加しようとしましたが、CopyLocalをfalseに設定しようとしましたが、私がFileNotFoundExceptionを取得したときにファイルまたはアセンブリを読み込めませんでした。

私はAppDomain.CurrentDomain.AssemblyResolveにイベントを追加しようとしましたが、そこにファイルをロードしようとしましたが、問題は私のプログラムが始まる前に例外が発生することです。最初の行にブレークポイントを置いても、ブレークポイントに達する前に例外がスローされます。

+0

一般的に、サードパーティのベンダーは、標準的なプラクティスに従わないと、そのコンポーネントを本番環境で使用する方法を説明しています(ここではそうです)。まともな文書はありませんか? –

+0

サイモン氏は、通常、サードパーティのアセンブリとの配布可能な契約があると述べています。 –

+0

できるだけ早く 'AssemblyResolve'イベントに参加していますか?早期に購読しないと、解決する前にサードパーティのアセンブリに依存するコードが実行される可能性があります。 –

答えて

9

C# 3.0 in a Nutshell, 3rd edition, by Joseph and Ben Albahari、p。 557-558:あなたがアプリケーションベースディレクトリ以外の場所にアセンブリを展開することもできます時々

ベースフォルダの外

展開アセンブリが [...] はこれを行うにはCLRがベースフォルダー外のアセンブリを見つけるのを支援する必要があります。最も簡単な解決策は、AssemblyResolveイベントを処理することです。

(私たちはあなたのケースでは、あなた以外の誰かがアセンブリを展開しているという事実を無視することができます。)あなたがしようとした

。しかし、非常に重要な手掛かりは後で少し後に続く。 2件のコードのコメントを読む:あなたが見たよう

public static void Loader 
{ 
    static void Main(string[] args) 
    { 
     AppDomain.CurrentDomain.AssemblyResolve += FindAssem; 

     // We must switch to another class before attempting to use 
     // any of the types in C:\ExtraAssemblies: 
     Program.Go(); 
    } 

    static Assembly FindAssem(object sender, ResolveEventArgs args) 
    { 
     string simpleName = new AssemblyName(args.Name).Name; 
     string path = @"C:\ExtraAssemblies\" + simpleName + ".dll"; 

     if (!File.Exists(path)) return null; 
     return Assembly.LoadFrom(path); 
    } 
} 

public class Program 
{ 
    public static void Go() 
    { 
     // Now we can reference types defined in C:\ExtraAssemblies 
    } 
} 

あなたは、外部のDLL どこでものいずれかから任意の型を参照してはなりません外部アセンブリを解決するクラス。もしそうなら、あなたのAssemblyResolveが実行される前にコードの実行が止まるでしょう。

+0

ビンゴ!参照されたアイテムの使用を、Main()があるクラス以外のクラスに移動すると、それが解決されました。ありがとう:) – aero

+0

P .:私は、この解決策が正式に文書化されているのか、一部のフレームワークのバージョンではうまくいくのかは分かりませんが、他者では失敗する可能性があることを私は認めません。したがって、私はHans Passantの最終声明に完全に同意します。より簡単な方法が必要です。 – stakx

+0

これは素晴らしいですよね! 質問:FindAssem()がnullを返す場合、Go()がFileNotFoundExceptionをスローしないようにするにはどうすればよいですか? – Eddie

4

JITコンパイラがアセンブリをロードする必要があるため、アプリケーションの爆弾が発生します。 Main()メソッドでアセンブリからの型の使用を慎重に避ける必要があります。それは難しいことではありません。別のMainメソッドを記述し、ジッタにそのメソッドをインライン化しないように指示する属性を与えます。この属性がなければ、オプティマイザがメソッドをインライン展開するときにReleaseビルドに爆発する可能性があります。このように:

using System; 
using System.Runtime.CompilerServices; 

class Program { 
    static void Main(string[] args) { 
     AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); 
     DelayedMain(args); 
    } 

    [MethodImpl(MethodImplOptions.NoInlining)] 
    static void DelayedMain(string[] args) { 
     // etc.. 
    } 


    static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { 
     // etc... 
    } 
} 

このようにする前に、ベンダーに連絡して推奨事項を尋ねてください。ライセンスの権利を行使するには、より簡単な方法が必要です。 GACは一般的な選択であり、おそらくあなたのdevマシンでgacutilを実行する必要があります。

関連する問題