EEFileLoadException عند استخدام فئات C# في C++ (تطبيق win32)

StackOverflow https://stackoverflow.com/questions/93770

  •  01-07-2019
  •  | 
  •  

سؤال

لأسباب تتعلق بالنشر، أحاول استخدام IJW لتغليف تجميع C# في C++ بدلاً من استخدام COM Callable Wrapper.

لقد فعلت ذلك في مشاريع أخرى، ولكن في هذا المشروع، أحصل على EEFileLoadException.سيكون موضع تقدير أي مساعدة!

كود غلاف C++ المُدار (هذا موجود في DLL):

extern "C" __declspec(dllexport) IMyObject* CreateMyObject(void)
{
    //this class references c# in the constructor
    return new CMyWrapper( );
}

extern "C" __declspec(dllexport)  void DeleteMyObject(IMyObject* pConfigFile)
{
    delete pConfigFile;
}

extern "C" __declspec(dllexport) void TestFunction(void)
{
    ::MessageBox(NULL, _T("My Message Box"), _T("Test"), MB_OK);
}

رمز الاختبار (هذا هو EXE):

typedef void* (*CreateObjectPtr)();
typedef void (*TestFunctionPtr)();

int _tmain testwrapper(int argc, TCHAR* argv[], TCHAR* envp[])
{
    HMODULE hModule = ::LoadLibrary(_T("MyWrapper"));
    _ASSERT(hModule != NULL);

    PVOID pFunc1 = ::GetProcAddress(hModule, "TestFunction");
    _ASSERT(pFunc1 != NULL);
    TestFunctionPtr pTest = (TestFunctionPtr)pFunc1;

    PVOID pFunc2 = ::GetProcAddress(hModule, "CreateMyObject");
    _ASSERT(pFunc2 != NULL);
    CreateObjectPtr pCreateObjectFunc = (CreateObjectPtr)pFunc2;

    (*pTest)();  //this successfully pops up a message box
    (*pCreateObjectFunc)();  //this tosses an EEFileLoadException

    return 0;
}

بالنسبة لما يستحقه، فإن سجل الأحداث يقدم ما يلي:.NET Runtime Version 2.0.50727.143 - خطأ محرك التنفيذ المميت (79F97075) (80131506)

ولسوء الحظ، مايكروسوفت ليس لديها معلومات حول هذا الخطأ.

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

المحلول

كانت المشكلة حيث توجد ملفات DLL.

  • ج:\dlls\managed.dll
  • ج:\dlls\wrapper.dll
  • ج:\exe\my.exe

لقد تأكدت من ذلك عن طريق نسخ Managed.dll إلى c:\exe وعمل بدون مشكلة.من الواضح أن CLR لن يبحث عن مكتبات DLL المُدارة في مسار ملف DLL غير المُدار وسيبحث عنها فقط حيث يوجد الملف القابل للتنفيذ.(أو في GAC).

لأسباب لا تستحق الخوض فيها، هذه هي البنية التي أحتاجها، مما يعني أنني بحاجة إلى مساعدة CLR في تحديد موقع ملف dll المُدار.انظر الكود أدناه:

محلل التجميع.h:

/// <summary>
/// Summary for AssemblyResolver
/// </summary>
public ref class AssemblyResolver
{
public:

static Assembly^ MyResolveEventHandler( Object^ sender, ResolveEventArgs^ args )
{
    Console::WriteLine( "Resolving..." );

    Assembly^ thisAssembly = Assembly::GetExecutingAssembly();
    String^ thisPath = thisAssembly->Location;
    String^ directory = Path::GetDirectoryName(thisPath);
    String^ pathToManagedAssembly = Path::Combine(directory, "managed.dll");

    Assembly^ newAssembly = Assembly::LoadFile(pathToManagedAssembly);
    return newAssembly;
}

};

التفاف.cpp:

#include "AssemblyResolver.h"

extern "C" __declspec(dllexport) IMyObject* CreateMyObject(void)
{
    try
    {
        AppDomain^ currentDomain = AppDomain::CurrentDomain;
        currentDomain->AssemblyResolve += gcnew ResolveEventHandler( AssemblyResolver::MyResolveEventHandler );

        return new CMyWrapper( );
    }
    catch(System::Exception^ e)
    {
        System::Console::WriteLine(e->Message);

        return NULL;
    }
}

نصائح أخرى

المشكلة الأولى هي التأكد من تعيين نوع مصحح الأخطاء على مختلط.ثم تحصل على استثناءات مفيدة.

بالنسبة للتطبيق الأصلي الذي يستهلك ملف dll للوضع المختلط (ملف EXE الخاص بك)، قم بتغيير **"نوع مصحح الأخطاء" إلى الوضع "المختلط".(انتقل إلى خصائص المشروع -> خصائص التكوين -> التصحيح)

هناك بعض النقاط الأخرى (التي قد لا تكون ذات صلة بك) ولكن في تجربتي يمكن أن تسبب مشاكل.- في نظام التشغيل Windows 8 (مع إجراءات أمنية مشددة)، يرجى محاولة تشغيل VS كمسؤول.- تأكد من أنك تستخدم ثنائيات x86 لتكوين x86.- انتبه للتحقق من StrongName، إذا كانت تجميعات C# الخاصة بك والتي تستهلكها في Managed C++ موقعة، فيرجى التفكير في التوقيع على ملف dll للوضع المختلط أيضًا.

نأمل أن يكون هذا يساعد.

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

على سبيل المثال، يجب أن يكون MyResolveEventHandler الخاص بك على شكل:

static Assembly^ MyResolveEventHandler( Object^ sender, ResolveEventArgs^ args )
{
    Console::WriteLine( "Resolving..." );

    String^ assemblyName = args->Name;

    // Strip irrelevant information, such as assembly, version etc.
    // Example: "Acme.Foobar, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
    if( assemblyName->Contains(",") ) 
    {
        assemblyName = assemblyName->Substring(0, assemblyName->IndexOf(","));
    }

    Assembly^ thisAssembly = Assembly::GetExecutingAssembly();
    String^ thisPath = thisAssembly->Location;
    String^ directory = Path::GetDirectoryName(thisPath);
    String^ pathToManagedAssembly = Path::Combine(directory, assemblyName );

    Assembly^ newAssembly = Assembly::LoadFile(pathToManagedAssembly);
    return newAssembly;
}

كنت أتلقى C++ EEFileLoadException الذي تم طرحه كثيرًا بواسطة iisexpress.exe أثناء تصحيح أخطاء تطبيق ASP.NET MVC.مكدس الاستدعاءات واستثناء C++ نفسه لم يكن مفيدًا جدًا في مساعدتي في تحديد المشكلة.

بعد النظر مباشرة إلى عنوان المؤشر الوارد في استثناء C++، اكتشفت أخيرًا سلسلة مكتبة كانت تشير إلى إصدار قديم لم يعد قيد الاستخدام.وكان هذا بدوره بسبب إدخال قديم في ملف web.config الخاص بي:

<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
    <assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" />
    <bindingRedirect oldVersion="0.0.0.0-3.0.1.0" newVersion="3.0.1.0" />
  </dependentAssembly> </assemblyBinding> </runtime>

لقد قمت بترقية العديد من مكتبات أمان Microsoft.Own عبر NuGet إلى الإصدار 4.0.30319 ولكن هذا السطر في التكوين كان يوجه الخادم لإعادة توجيه المكالمات إلى الإصدار 3.0.1.0، والذي لم يعد الآن جزءًا من مشروعي.أدى تحديث التكوين إلى حل مشاكلي.

عند تشغيل مشروع مصحح الأخطاء C++ الأصلي الذي يستخدم dll المُدار بواسطة C++، قد تحصل على هذا الاستثناء.عندما يلتقطه VS2010 وسيتم إحباط تطبيقك بعد بعض استثناءات السلسلة، يمكنك محاولة تعطيل عامل تصفية الاستثناءات (القائمة|التصحيح|الاستثناء) لجميع استثناءات C++.ستظل ترى هذا الاستثناء في المخرجات ولكن لن يتم إحباط تطبيقك

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