For deployment reasons, I am trying to use IJW to wrap a C# assembly in C++ instead of using a COM Callable Wrapper.
I\'ve done it on other projects, but on this o
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)
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.
Hope this would help.
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
The problem was where the DLLs were located.
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).
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:
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:
#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;
}
}
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.
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:
<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.
The first issue is to make sure the Debugger type is set to mixed. Then you get useful exceptions.
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:
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;
}