C# to C++/CLI to C DLL System.IO.FileNotFoundException

十年热恋 提交于 2019-11-30 20:06:45

Are the C and C++ DLLs in the same directory as the C# assembly that's executing?

You may have to change your project output settings so that the C# assembly and the other DLLs all end up in the same folder.

I've often used the Dependency Walker in cases like this; it's a sanity check that shows that all the dependencies can actually be found.

Once your app is running, you may also want to try out Process Monitor on the code you are running, to see which DLLs are being referenced, and where they are located.

Andy Dent

The answer for the GUI, other than changing output settings, was the addition of a Pre-Build Step

copy $(ProjectDir)..\Debug\BackingStore.* $(TargetDir)

The answer for the Test projects was to add the missing DLL to the Deployment tab of the testrunconfig. You can either do so by directly editing the default LocalTestRun.testrunconfig (appears in Solution under Solution Items) or right-click the Solution and Add a new test run config, which will then appear under the main Test menu.

Thanks for the answers on this SO question on test configurations for leading me to the answer.

The reason why this happens is because you either are loading DLLMAIN from managed code, before the CRT has an opportunity to be initialized. You may not have any managed code, be executed DIRECTLY or INDERECTLY from an effect of DllMain notifications. (See: Expert C++/CLI: .Net for Visual C++ Programmers, chapter 11++).

Or you have no native entrypoint defined wahtsoever, yet you have linked to MSVCRT. The CLR is automatically initialized for you with /clr, this detail causes a lot of confusion and must be taken into account. A mixed mode DLL actually delay loads the CLR through the use of hot-patching all of the managed entry point vtables in your classes.

A number of class initialization issues surround this topic, loader lock and delay loading CLR are a bit trickey sometimes. Try to declare global's static and do not use #pragma managed/unmanaged, isolate your code with /clr per-file.

If you can not isolate your code from the managed code, and are having trouble, (after taking some of these steps), you can also look towards hosting the CLR yourself and perhaps going through the effort of creating a domain manager, that would ensure your fully "in-the-loop" of runtime events and bootstrapping.

This is exactally why, it has nothting todo with your search path, or initialization. Unfortunately the Fusion log viewer does not help that much (which is the usual place to look for .NET CLR assembly binding issues not dependency walker).

Linking statically has nothing todo with this either. You can NOT statically link a C++/CLI application which is mixed mode.

  1. Place your DLLMAIN function into a file by itself.
  2. Ensure that this file does NOT have /CLR set in the build options (file build options)
  3. Make sure your linking with /MD or /MDd, and all your dependencies which you LINK use the exact same CRT.
  4. Evaluate your linker's settings for /DEFAULTLIB and /INCLUDE to identify any possiable reference issues, you can declare a prototype in your code and use /INCLUDE to override default library link resolution.

Good luck, also check that book it's very good.

Randolpho

This is an interesting dilemma. I've never heard of a problem loading native .DLLs from C++/CLI after a call into it from C# before. I can only assume the problem is as @Daniel L suggested, and that your .DLL simply isn't in a path the assembly loader can find.

If Daniel's suggestion doesn't work out, I suggest you try statically linking the native C code to the C++/CLI program, if you can. That would certainly solve the problem, as the .DLL would then be entirely absorbed into the C++/CLI .DLL.

Make sure the target system has the correct MS Visual C runtime, and that you are not accidentally building the C dll with a debug runtime.

Had the same problem switching to 64-bit Vista. Our application was calling Win32 DLLs which was confusing the target build for the application. To resolve it we did the following:

  1. Go to project properties;
  2. Select Build tab;
  3. Change 'Platform target:' option to x86;
  4. Rebuild the application.

When I re-ran the application it worked.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!