アセンブリを使用するマネージドアプリがあります。そのアセンブリは、管理されていないC++コードを使用します。
マネージC++コードはdll内にあり、他のいくつかのdllに依存しています。これらのDLLはすべて、このコードによってロードされます。(ImageCore.dllが依存するすべてのdllを最初にロードするので、どのdllが欠落しているかがわかります。そうでない場合、ImageCore.dllのロードに失敗したために表示され、ログファイルには理由がわかりません)。
class Interop
{
private const int DONT_RESOLVE_DLL_REFERENCES = 1;
private static log4net.ILog log = log4net.LogManager.GetLogger("Imagecore.NET");
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr LoadLibraryEx(string fileName, IntPtr dummy, int flags);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern IntPtr FreeLibrary(IntPtr hModule);
static private String[] libs = { "log4cplus.dll", "yaz.dll", "zlib1.dll", "libxml2.dll" };
public static void PreloadAssemblies()
{
for (int i=0; i < libs.Length; ++i) {
String libname = libs[i];
IntPtr hModule = LoadLibraryEx(libname, IntPtr.Zero, DONT_RESOLVE_DLL_REFERENCES);
if(hModule == IntPtr.Zero) {
log.Error("Unable to pre-load '" + libname + "'");
throw new DllNotFoundException("Unable to pre-load '" + libname + "'");
} else {
FreeLibrary(hModule);
}
}
IntPtr h = LoadLibraryEx("ImageCore.dll", IntPtr.Zero, 0);
if (h == IntPtr.Zero) {
throw new DllNotFoundException("Unable to pre-load ImageCore.dll");
}
}
}
そして、このコードはによって呼び出されます
public class ImageDoc : IDisposable {
static ImageDoc()
{
ImageHawk.ImageCore.Utility.Interop.PreloadAssemblies();
}
...
}
これは静的コンストラクターです。
私が理解できる限りでは、ImageDocオブジェクトを使用しようとするとすぐに、そのアセンブリを含むdllが読み込まれ、その読み込みの一部として静的コンストラクターが呼び出されます。これにより、他のいくつかのDLLが次のように読み込まれます。良い。私が理解しようとしているのは、静的コンストラクターのためにキックアウトされているこのローダーロックにsmack dabを実行しないように、これらのDLLのロードをどのように延期するかです。
私はこれを見て、これだけをつなぎ合わせました。
- http://social.msdn.microsoft.com/Forums/en-US/vsto/thread/dd192d7e-ce92-49ce-beef-3816c88e5a86
- http://msdn.microsoft.com/en-us/library/aa290048%28VS.71%29.aspx
- http://forums.devx.com/showthread.php?t=53529
- http://www.yoda.arachsys.com/csharp/beforefieldinit.html
しかし、クラスがロードされている時点で発生しない限り、これらの外部DLLをロードする方法を見つけることができないようです。これらのLoadLibrary呼び出しを静的コンストラクターから取得する必要があると思いますが、必要になる前に呼び出す方法がわかりません(ここでの実行方法を除く)。このアセンブリを使用するすべてのアプリに、このようなdllの知識を入れる必要はありません。(そして、それで問題が解決するかどうかはわかりません...。
奇妙なことに、例外はデバッガーの外部で実行されている間ではなく、デバッガー内で実行されているときにのみ発生しているように見えます。
次の問題を実行せずに、これらのDLLをロードするにはどうすればよいですか。
LoadLibrary <- .NET loads the class from assembly dll
DllMain
LoadLibrary <- -Due to Static ctor
DllMain