سؤال

يتعلق هذا السؤال بموقع ASP.NET، الذي تم تطويره في الأصل في VS 2005 والآن في VS 2008.

يستخدم موقع الويب هذا ملفي DLL خارجيين غير مُدارين وهما ليسا .NET وليس لدي كود المصدر لتجميعهما ويجب أن أستخدمهما كما هو.

يعمل موقع الويب هذا بشكل جيد من داخل Visual Studio، حيث يحدد موقع ملفات DLL الخارجية هذه ويصل إليها بشكل صحيح.ومع ذلك، عندما يتم نشر موقع الويب على خادم ويب (يعمل على IIS6 وASP.NET 2.0) بدلاً من جهاز الكمبيوتر الخاص بالتطوير، فإنه لا يمكنه تحديد موقع مكتبات الارتباط الحيوي (DLL) الخارجية هذه والوصول إليها، وأحصل على الخطأ التالي:

Unable to load DLL 'XYZ.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)

توجد مكتبات DLL الخارجية في دليل bin الخاص بموقع الويب، إلى جانب مكتبات DLL المُدارة التي تغلفها وجميع مكتبات DLL الأخرى لموقع الويب.

يكشف البحث في هذه المشكلة أن العديد من الأشخاص الآخرين يبدو أنهم يواجهون نفس المشكلة في الوصول إلى ملفات DLL الخارجية بخلاف NET من مواقع ASP.NET، لكنني لم أجد حلاً ناجحًا.

لقد حاولت ما يلي:

  • يعتمد التشغيل على التحقق من التبعيات لإثبات أن الثلاثة الأولى موجودة في دليل System32 في المسار ، والآخر في إطار .NET 2.
  • لقد وضعت DLLs وتبعيهما في System32 وأعدت تشغيل الخادم ، لكن موقع الويب لا يزال قادرًا على تحميل هذه DLLs الخارجية.
  • منحت حقوقًا كاملة لـ ASPNET و IIS_WPG و IUSR (لهذا الخادم) إلى دليل BIN موقع الويب وإعادة تشغيله ، ولكن لا يزال موقع الويب لا يمكنه تحميل هذه DLLs الخارجية.
  • تمت إضافة DLLs الخارجية كعناصر موجودة للمشاريع وتعيين "النسخ إلى الإخراج" الخاصية "بنسخ دائمًا" ، ولا يزال موقع الويب لا يمكن العثور على DLLs.
  • قم أيضًا بتعيين خاصية "Build Action" على "المورد المدمج" وما زال موقع الويب لا يمكنه العثور على DLLs.

أي مساعدة في هذه المشكلة سيكون موضع تقدير كبير!

هل كانت مفيدة؟

المحلول

حاول وضع ملفات dll في الدليل \System32\Inetsrv.هذا هو دليل العمل لـ IIS على Windows Server.

إذا لم ينجح ذلك، فحاول وضع ملفات dll في دليل System32 وملفات التبعية في دليل Inetsrv.

نصائح أخرى

يحدث هذا بسبب نسخ ملفات dll المُدارة في الظل إلى موقع مؤقت ضمن دليل .NET Framework.يرى http://msdn.microsoft.com/en-us/library/ms366723.aspx للتفاصيل.

لسوء الحظ، لا يتم نسخ ملفات dll غير المُدارة ولن تتمكن عملية ASP.NET من العثور عليها عندما تحتاج إلى تحميلها.

أحد الحلول السهلة هو وضع ملفات dll غير المُدارة في دليل موجود في مسار النظام (اكتب "مسار" في سطر الأوامر لرؤية المسار على جهازك) بحيث يمكن العثور عليها من خلال عملية ASP.NET.الدليل System32 هو دائماً في المسار، لذا فإن وضع ملفات dll غير المُدارة هناك يعمل دائمًا، لكنني أوصي بإضافة مجلد آخر إلى المسار ثم إضافة ملفات dll هناك لمنع تلويث دليل System32.أحد العوائق الكبيرة لهذه الطريقة هو أنه يتعين عليك إعادة تسمية ملفات dll غير المُدارة لكل إصدار من تطبيقك ويمكنك الحصول بسرعة على ملف dll الخاص بك.

كبديل لوضع ملف dll في مجلد موجود بالفعل في المسار (مثل system32)، يمكنك تغيير قيمة المسار في العملية الخاصة بك باستخدام التعليمة البرمجية التالية

System.Environment.SetEnvironmentVariable("Path", searchPath + ";" + oldPath)

ثم عندما يحاول LoadLibrary العثور على ملف DLL غير المُدار، فإنه سيقوم أيضًا بفحص مسار البحث.قد يكون هذا أفضل من إحداث فوضى في System32 أو المجلدات الأخرى.

إضافة إلى إجابة مات، هذا هو ما نجح أخيرًا بالنسبة لي مع خادم 64 بت 2003/IIS 6:

  1. تأكد من أن dlls/asp.net الخاص بك هو نفس الإصدار (32/64 بت)
  2. ضع ملفات dll غير المُدارة في inetsrv dir (لاحظ أنه في نظام التشغيل Windows 64 بت، يكون هذا ضمن syswow64، على الرغم من إنشاء دليل sys32/inetsrv)
  3. اترك ملفات dll المُدارة في /bin
  4. تأكد من أن كلا مجموعتي ملفات dll تتمتعان بأذونات القراءة/التنفيذ

ألق نظرة مع FileMon أو ProcMon وقم بتصفية أسماء ملفات DLL المزعجة.سيُظهر لك هذا الأدلة التي تم فحصها بحثًا عن مكتبات الارتباط الحيوي (DLL)، وأي مشكلات تتعلق بالأذونات قد تكون لديك.

هناك خيار آخر وهو تضمين مكتبة الارتباط الحيوي (DLL) الأصلية كمورد في مكتبة الارتباط الحيوي (DLL) المُدارة.يعد هذا أكثر تعقيدًا في ASP.NET، لأنه يتطلب الكتابة إلى مجلد مؤقت في وقت التشغيل. تم شرح هذه التقنية في إجابة SO أخرى.

يستحق دائما التحقق من المسار متغير في إعدادات البيئة الخاصة بك أيضًا.

قم بتشغيل DEPENDS على XYZ.dll مباشرة، في الموقع الذي قمت بنشره فيه.إذا لم يكشف ذلك عن أي شيء مفقود، فاستخدم أداة fuslogvw في النظام الأساسي SDK لتتبع أخطاء أداة التحميل.كما تحتوي سجلات الأحداث أحيانًا على معلومات حول حالات الفشل في تحميل مكتبات الارتباط الحيوي (DLL).

لقد واجهت نفس المشكلة.وقد جربت جميع الخيارات المذكورة أعلاه، والنسخ إلى system32، وinetpub، وإعداد بيئة المسار، وما إلى ذلك، لم ينجح أي شيء.تم حل هذه المشكلة أخيرًا عن طريق نسخ ملف dll غير المُدار إلى دليل bin لتطبيق الويب أو خدمة الويب.

بعد معاناة طوال اليوم حول هذه المشكلة وأخيراً وجدت الحل الذي يناسبني.إنه مجرد اختبار، لكن الطريقة ناجحة.

namespace TestDetNet
{
    static class NativeMethods
    {
        [DllImport("kernel32.dll")]
        public static extern IntPtr LoadLibrary(string dllToLoad);

        [DllImport("kernel32.dll")]
        public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);


        [DllImport("kernel32.dll")]
        public static extern bool FreeLibrary(IntPtr hModule);
    }

    public partial class _Default : System.Web.UI.Page
    {
        [UnmanagedFunctionPointer(CallingConvention.StdCall)]
        private delegate int GetRandom();

        protected System.Web.UI.WebControls.Label Label1;
        protected void Page_Load(object sender, EventArgs e)
        {
            Label1.Text = "Hell'ou";
            Label1.Font.Italic = true;
        }

        protected void Button1_Click(object sender, EventArgs e)
        {
            if (File.Exists(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll")) {
                IntPtr pDll = NativeMethods.LoadLibrary(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll");
                if (pDll == IntPtr.Zero) { Label1.Text =  "pDll is zero"; }
                else
                {
                  IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "GetRandom");
                  if (pAddressOfFunctionToCall == IntPtr.Zero) { Label1.Text += "IntPtr is zero";   }
                  else
                  {
                    GetRandom _getRandom = (GetRandom)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(GetRandom));

                    int theResult = _getRandom();

                    bool result = NativeMethods.FreeLibrary(pDll);
                    Label1.Text = theResult.ToString();
                  }
                }
          }
        }
    }
}

في Application_start استخدم هذا:(قم بتخصيص المجلدات /bin/x64 وbin/dll/x64 حسب الحاجة)

String _path = String.Concat(System.Environment.GetEnvironmentVariable("PATH")
                ,";"
                , System.Web.Hosting.HostingEnvironment.MapPath("~/bin/x64")
                ,";"
                , System.Web.Hosting.HostingEnvironment.MapPath("~/bin/dll/x64")
                ,";"
                );
            System.Environment.SetEnvironmentVariable("PATH", _path, EnvironmentVariableTarget.Process);
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top