У нас есть управляемое приложение, которое использует сборку. Эта сборка использует некоторый неуправляемый код C ++.
Управляемый код C ++ находится в dll, что зависит от нескольких других dll. Все эти Dll загружены этим кодом. (Мы загружаем все библиотеки DLL, от которых зависит ImageCore.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-библиотек быть загруженным также. Я пытаюсь понять, как мы откладываем загрузку этих библиотек DLL, чтобы мы не запускали smack dab в эту блокировку загрузчика, которая отключается из-за статического конструктора.
Я сложил это так, посмотрев на:
- 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