0

I'm trying to build a VS 2005 website project which depends on several managed C++ assemblies. One of the managed C++ assemblies depends (static-load) on an unmanaged DLL which uses __declspec(dllexport) to export classes.

For some reason, I get the following build error:

Error   4   The specified module could not be found. (Exception from HRESULT: 0x8007007E)       

(From build output details):

(0): Build (web): The specified module could not be found. (Exception from HRESULT: 0x8007007E)

when I build with the unmanaged DLL in the website's \Bin\ directory, but not in the path. If I put the unmanaged DLL in the path, then re-start visual studio, it builds and runs just fine.

Note: This thread seemed related, but I haven't gotten as far as deployment yet: Unmanaged DLLs fail to load on ASP.NET server

Is there any way to get this .sln building correctly with unmanaged DLL's in \Bin\ rather than the path? (I'd really prefer to keep these as part of the website, not the system)

Edit: It seems I've misunderstood the purpose of the \Bin\ folder to some degree. Sounds like nothing except managed assemblies should go there. (So COM objects and other unmanaged DLLs they rely on which I've been placing there probably belong someplace else.)

Community
  • 1
  • 1

1 Answers1

1

I believe that ASP.NET copies your assemblies around quite a bit, to avoid locking the original DLL (which would prevent overwriting with a newer version). Then when you do overwrite it, it needs a copy of the old version until all outstanding requests complete, alongside the new version being used for new requests.

In summary, your DLL doesn't run from the \bin\ directory where you put it, and it looks for native dependencies where it actually does run.

Your options are to put the native DLLs in the path, or else add code to explicitly copy them to the "real" assembly directory as needed. But your code shouldn't even have permission to write to the filesystem, so I think you're stuck using the path.

Do note, though, that you can add directories to the application's own environment, without affecting the global path. For example, p/invoke SetDllDirectory Don't add \bin\ though. Put your native DLLs in a separate directory like \bin\native or \bin\x86, so when you change the search path you don't change which managed DLLs are found.

Edit: This only works if the managed DLL delay loads any unmanaged native DLLs it links against (using /DELAYLOAD). Otherwise compilation of global.asax (or wherever the path setting happens) will fail.

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • Great, how do I add directories to IIS5 or IIS6 path? (Or do I just make a custom user profile with the path I need?) C:\inetpub\wwwroot\\bin\ seems like a pretty obvious thing to add to IIS path... (also note: csc.exe seems to have a /linkresource directive, but I'm not having luck with it so far.) –  Jan 27 '12 at 16:30
  • DON'T add the `bin` directory containing managed assemblies, this will interfere with the ASP.NET assembly versioning system. DO use a subdirectory for your unmanaged DLLs. Isn't there a `WebApplication_Load` event you can handle from the ASP.NET code-behind page before using the C++/CLI assembly? – Ben Voigt Jan 27 '12 at 17:40
  • I certainly don't expect there to be a page event. Putting this assembly in an IIS website kills the whole site even if only one page accesses it. –  Jan 27 '12 at 18:09
  • "To execute code when a web application first starts, we need to create a special file named Global.asax. This file can contain event handlers for application-, session-, and request-level events, and it is here where we can add code that will be executed whenever the application starts." -- from http://www.asp.net/web-forms/tutorials/data-access/caching-data/caching-data-at-application-startup-cs – Ben Voigt Jan 27 '12 at 19:36
  • global.asax has to be compiled whenever it is changed. This error occurs during compilation. (If I move files to the path to get past compilation and then never change the file, it'd work, but if global.asax is ever changed and then iisreset things break.) –  Jan 27 '12 at 19:58
  • @ebyrob: Say what? Compilation requires the dependency of a dependency? Then ASP.NET is more confused than I ever imagined. – Ben Voigt Jan 27 '12 at 20:16
  • It's a problem specific to deploying IIS websites in source form. IIS loads every assembly in the \Bin\ directory before it compiles any source file in the website. –  Jan 27 '12 at 20:23
  • @ebyrob: Do you have source for the unmanaged DLL? If so, you could link it into the C++/CLI DLL as a static library instead of a separate DLL. – Ben Voigt Jan 27 '12 at 20:57
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/7116/discussion-between-ebyrob-and-ben-voigt) –  Jan 27 '12 at 20:59
  • So, I finally figured out how to get this working... I had to make sure the native DLL is delay loaded (using /DELAYLOAD). At that point I'm free to safely put code in global.asax to tweak the path or DLL directory. –  Feb 01 '12 at 20:58