سؤال

لدينا تطبيق مُدار ، يستخدم التجميع. يستخدم هذا التجميع بعض كود C ++ غير المدير.

رمز C ++ المدار في DLL ، وهذا يعتمد على العديد من DLLs الأخرى. يتم تحميل كل هذه DLLs بواسطة هذا الرمز. (نقوم بتحميل جميع 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. نحن سوف. ما أحاول اكتشافه ، هو كيف يمكننا تأجيل تحميل DLLs هذه حتى لا ندير صفعًا في قفل المحمل هذا الذي يتم طرده بسبب المنشئ الثابت.

لقد جمعت هذا كثيرًا معًا من خلال النظر إلى:

  1. http://social.msdn.microsoft.com/forums/en-us/vsto/thread/dd192d7e-ce92-49ce-beef-3816c88e5a86
  2. http://msdn.microsoft.com/en-us/library/aa290048٪28vs.71٪29.aspx
  3. http://forums.devx.com/showthread.php؟t=53529
  4. http://www.yoda.arachsys.com/csharp/beforefieldinit.html

لكن لا يمكنني العثور على طريقة للحصول على هذه DLL الخارجية لتحميلها دون حدوثها عند النقطة التي يتم تحميل الفئة. أعتقد أنني بحاجة إلى الحصول على مكالمات التحميل هذه من المنشئ الثابت ، لكن لا أعرف كيفية استدعاءها قبل الحاجة إليها (باستثناء كيفية القيام بها هنا). أفضل ألا أضطر إلى وضع هذا النوع من المعرفة بـ DLLs في كل تطبيق يستخدم هذا التجميع. (ولست متأكدًا من أن هذا سيصلح المشكلة ....

الشيء الغريب هو أن الاستثناء يبدو أنه يحدث فقط أثناء الركض داخل مصحح الأخطاء ، وليس أثناء الركض خارج مصحح الأخطاء.

كيف أتمكن

LoadLibrary <- .NET loads the class from assembly dll 
DllMain 
LoadLibrary <- -Due to Static ctor 
DllMain
هل كانت مفيدة؟

المحلول

Loaderlock هو MDA (مساعد تصحيح الأخطاء) تحذير من تصحيح الأخطاء. يخبرك أن هناك ربما كن مشكلة في الكود. يحدث ذلك فقط عند الركض تحت تصحيح الأخطاء لأن تصحيح الأخطاء هو الذي يقوم بتحقق MDA لإبلاغك بأنه في بعض الحالات ، يتم توطينك "مايو تحدث".

لسوء الحظ ، لا يمكنني مساعدتك أكثر من ذلك بكثير. تجربتي في LoaderLock هي أن (أ) تحذير غامض يمنحك VS ، ولكن هناك دعم قليل ثمينًا يخبرك بما يجب عليك فعله فعليًا ، و (ب) تم تشغيل تطبيقنا لمدة 4 سنوات مع LoaderLock الخروج (في DirectX ، لذلك ليس حتى في الكود لدينا) ولم يسببه أبدًا مشكلة ، بخلاف كونه متاعب مزعجة في كل مرة نركض فيها تحت تصحيح الأخطاء. ymmv بالطبع.

(يمكنك تعطيل MDA في Debug -> الاستثناءات في قسم مساعدي التصحيح المدارة ، ولكن في كل مرة تقوم فيها بإعادة ضبط هذه الإعدادات ، تعمل MDA لعنة) مرة أخرى)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top