在 C++(win32 应用程序)中使用 C# 类时出现 EEFileLoadException
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/93770/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
EEFileLoadException when using C# classes in C++(win32 app)
提问by Adam Tegen
For deployment reasons, I am trying to use IJW to wrap a C# assembly in C++ instead of using a COM Callable Wrapper.
出于部署原因,我尝试使用 IJW 将 C# 程序集包装在 C++ 中,而不是使用 COM Callable Wrapper。
I've done it on other projects, but on this one, I am getting an EEFileLoadException. Any help would be appreciated!
我已经在其他项目上完成了它,但是在这个项目上,我收到了 EEFileLoadException。任何帮助,将不胜感激!
Managed C++ wrapper code (this is in a DLL):
托管 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);
}
Test Code (this is an EXE):
测试代码(这是一个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;
}
For what it's worth, the Event Log reports the following: .NET Runtime version 2.0.50727.143 - Fatal Execution Engine Error (79F97075) (80131506)
值得一提的是,事件日志报告了以下内容:.NET 运行时版本 2.0.50727.143 - 致命执行引擎错误 (79F97075) (80131506)
Unfortunately, Microsoft has no information on that error.
不幸的是,微软没有关于该错误的信息。
采纳答案by Adam Tegen
The problem was where the DLLs were located.
问题在于 DLL 的位置。
- c:\dlls\managed.dll
- c:\dlls\wrapper.dll
- c:\exe\my.exe
- c:\dlls\managed.dll
- c:\dlls\wrapper.dll
- c:\exe\my.exe
I confirmed this by copying managed.dll into c:\exe and it worked without issue. Apparently, the CLR won't look for managed DLLs in the path of the unmanaged DLL and will only look for it where the executable is. (or in the GAC).
我通过将 managed.dll 复制到 c:\exe 来确认这一点,并且它没有问题。显然,CLR 不会在非托管 DLL 的路径中查找托管 DLL,而只会在可执行文件所在的位置查找它。(或在 GAC 中)。
For reasons not worth going into, this is the structure I need, which meant that I needed to give the CLR a hand in located the managed dll. See code below:
由于不值得深入研究的原因,这是我需要的结构,这意味着我需要让 CLR 帮助定位托管 dll。见下面的代码:
AssemblyResolver.h:
AssemblyResolver.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;
}
};
Wrapper.cpp:
包装器.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;
}
}
回答by Adam Tegen
The first issue is to make sure the Debugger type is set to mixed. Then you get useful exceptions.
第一个问题是确保调试器类型设置为混合。然后你会得到有用的异常。
回答by tomanu
When you run in debugger C++ native project which use C++ managed dll you may get this exception. When VS2010 catch it and your application after some chain exceptions will be aborted you may try in exception filter (Menu|Debug|Excpetion) disable all C++ exceptions. You will still see this exception in output but your application won't abort
当您在使用 C++ 托管 dll 的调试器 C++ 本机项目中运行时,您可能会遇到此异常。当 VS2010 捕获它并且您的应用程序在一些链异常之后将被中止时,您可以尝试在异常过滤器 (Menu|Debug|Excpetion) 中禁用所有 C++ 异常。您仍会在输出中看到此异常,但您的应用程序不会中止
回答by Fredrik Ullner
In case anyone else stumbles upon this question, and you are using a dynamic assembly name: make sure you are stripping the assembly name, it may contain version, culture and other content that you may not use.
万一其他人偶然发现这个问题,并且您正在使用动态程序集名称:确保您正在剥离程序集名称,它可能包含您可能不使用的版本、区域性和其他内容。
I.e., your MyResolveEventHandler should be in the form of:
即,您的 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;
}
回答by A.B.
For you native application consuming the mixed mode dll (Your EXE), change the **"Debugger Type" to "Mixed" mode. (Go to Project Properties -> Configuration Properties -> Debugging)
对于使用混合模式 dll(您的 EXE)的本机应用程序,请将 **“调试器类型”更改为“混合”模式。(转到项目属性 -> 配置属性 -> 调试)
There are some other points (which might not be relevant to you) but in my experience they could cause issues. - On windows 8 (with tighter security) please try launching your VS as admin. - Make sure that for x86 configuration you are using x86 binaries. - Watch for StrongName verification, if your C# assemblies which you are consuming in Managed C++ as signed, please consider signing the mixed mode dll too.
还有一些其他要点(可能与您无关),但根据我的经验,它们可能会导致问题。- 在 Windows 8(安全性更高)上,请尝试以管理员身份启动您的 VS。- 确保对于 x86 配置,您使用的是 x86 二进制文件。- 注意 StrongName 验证,如果您在托管 C++ 中使用的 C# 程序集已签名,请考虑对混合模式 dll 进行签名。
Hope this would help.
希望这会有所帮助。
回答by Gareth
I was getting the C++ EEFileLoadException thrown a lot by iisexpress.exe during debugging of an ASP.NET MVC application. The call stack and C++ exception itself were not terribly helpful in helping me pin down the problem.
在调试 ASP.NET MVC 应用程序期间,我发现 iisexpress.exe 抛出了很多 C++ EEFileLoadException。调用堆栈和 C++ 异常本身并没有帮助我确定问题。
After looking directly at the pointer address given in the C++ exception I eventually discovered a library string which was pointing to an old version no longer in use. This in turn was due to an out-of-date entry in my web.config file:
在直接查看 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>
I had upgraded various Microsoft.Own security libraries via NuGet to version 4.0.30319 but this line in the config was instructing the server to redirect calls to version 3.0.1.0, which was now no longer part of my project. Updating the config resovled my problems.
我已通过 NuGet 将各种 Microsoft.Own 安全库升级到版本 4.0.30319,但配置中的这一行指示服务器将调用重定向到版本 3.0.1.0,该版本现在不再是我项目的一部分。更新配置解决了我的问题。