"module could not be found" error with C++/CLI component in ASP.NET
Asked Answered
C

2

10

I have to include a (managed) C++/CLI component in one of my ASP.NET projects, that references for itself some other (unmanaged) C++ DLLs. Should be no problem - .NET 3.5 is happy when compiling the project, everything seems fine. The C++/CLI component and the other C++ DLLs are compiled by another department as Release version with "Any CPU" in Visual Studio 2005. The VC++ 2005 Redistributable package is installed. And the same code works without problem when I run it inside of a normal .NET console application.

Now while this code works in a console app, it's not being hosted correctly by ASP.NET - it leads an error on the initial page load (even before stepping into the Global.asax). For testing and debugging, I have used two machine configurations:

  1. Local Dev PC: Windows XP, 32 Bit, VC++ 2005 Redist Package, Visual Studio 2010, ASP.NET 3.5, Compiling "Any CPU", Hosting in Web Development Server (Cassini)
  2. Test Server (target machine): Windows 7, 64 Bit, VC++ 2005 Redist Package, Hosting in IIS 7, AppPool has "Enable 32-Bit Applications" set

On both machines the same following error occurs when I start the ASP.NET application:

Exception Details: System.IO.FileNotFoundException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)

Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:
[FileNotFoundException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)]
 System.Reflection.Assembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +0
 System.Reflection.Assembly.nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, Assembly locationHint, StackCrawlMark& stackMark, Boolean throwOnFileNotFound, Boolean forIntrospection) +43
 System.Reflection.Assembly.InternalLoad(AssemblyName assemblyRef, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +127
 System.Reflection.Assembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +142
 System.Reflection.Assembly.Load(String assemblyString) +28
 System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +46

[ConfigurationErrorsException: The specified module could not be found. (Exception from HRESULT: 0x8007007E)]
 System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +613
 System.Web.Configuration.CompilationSection.LoadAllAssembliesFromAppDomainBinDirectory() +203
 System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +105
 System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +178
 System.Web.Compilation.WebDirectoryBatchCompiler..ctor(VirtualDirectory vdir) +163
 System.Web.Compilation.BuildManager.BatchCompileWebDirectoryInternal(VirtualDirectory vdir, Boolean ignoreErrors) +53
 System.Web.Compilation.BuildManager.BatchCompileWebDirectory(VirtualDirectory vdir, VirtualPath virtualDir, Boolean ignoreErrors) +175
 System.Web.Compilation.BuildManager.CompileWebFile(VirtualPath virtualPath) +86
 System.Web.Compilation.BuildManager.GetVPathBuildResultInternal(VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) +261
 System.Web.Compilation.BuildManager.GetVPathBuildResultWithNoAssert(HttpContext context, VirtualPath virtualPath, Boolean noBuild, Boolean allowCrossApp, Boolean allowBuildInPrecompile) +101
 System.Web.Compilation.BuildManager.GetVirtualPathObjectFactory(VirtualPath virtualPath, HttpContext context, Boolean allowCrossApp, Boolean noAssert) +126
 System.Web.Compilation.BuildManager.CreateInstanceFromVirtualPath(VirtualPath virtualPath, Type requiredBaseType, HttpContext context, Boolean allowCrossApp, Boolean noAssert) +62
 System.Web.UI.PageHandlerFactory.GetHandlerHelper(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +33
 System.Web.UI.PageHandlerFactory.System.Web.IHttpHandlerFactory2.GetHandler(HttpContext context, String requestType, VirtualPath virtualPath, String physicalPath) +40
 System.Web.HttpApplication.MapHttpHandler(HttpContext context, String requestType, VirtualPath path, String pathTranslated, Boolean useAppConfig) +160
 System.Web.MapHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +93
 System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155

Now this is weird... It doesn't say anything about what assembly is missing, even Fuslogvw.exe or sxstrace.exe aren't logging anything. Moreover of coures it seems that the error depends on the C++/CLI assembly or on the unmanaged C++ DLLs. If I remove the C++/CLI assembly reference from my ASP.NET project and the code, it works fine. Now because the C++/CLI assembly depends on native C++ DLLs that are not referenced in the ASP.NET project, I copied all dependent C++ DLLs to the "bin" folder of the ASP.NET project's output folder (same as for the workgin console application). While every C++ stuff has been compiled in Release mode, with the correct VC++ Redist Package installed, there should be all dependencies in place. Of course I know there is a FileNotFoundException, but I cannot work out what's missing...

As said: the same code for accessing the C++/CLI component works in a .NET 3.5 console application on both test PCs (where I have the same dependencies deployed) with the same dependent C++ DLLs deployed into the output folder, just in ASP.NET I get the above error.

Any suggestions how I can get rid of the problem or how I can track it further?

(Of course I searched StackOverflow and Google for the problem, e.g. I found these links, but they didn't help:
- "The specified module could not be found" error when running C# ASP.NET web service referring C++ dll
- Access x86 COM from x64 .NET
- ASP.NET application developed in 32 bit environment not working in 64 bit environment
- Module Not Found Exception From .NET 2.0 Web Service On Windows Server 2008 R2 )

Contrast answered 9/2, 2012 at 9:11 Comment(0)
C
4

Your code reach the _nLoad and this is good because have pass all checks for loading and move to the core to actually load the dll, and there its fail.

For start download the Dependency Walker from http://www.dependencywalker.com/ and use it on dll to find out what other resource this dll needs to run. I suspect that can not load some other dll files.

Additional maybe this dll search for other files that can not find and thats why can not load. The second way is to use the File Monitor, or the Process Monitor from sysinternals to find what fail to load.

http://technet.microsoft.com/en-us/sysinternals
http://technet.microsoft.com/en-us/sysinternals/bb896645

Colvert answered 9/2, 2012 at 9:28 Comment(8)
Thanks at first. I've used Dependency Walker before without finding any problems. I just wonder why the .NET console application with the same deployed assemblies works, while the ASP.NET application fails? That's weird...Contrast
@Contrast as I write, probably because fail to load some resource files. Use also the file monitor to find them out.Colvert
Ok, with ProcMon (first time user) I've gone a step further (thanks!), but hopefully you can explain the results: I saw that the WebDev.WebServer20.exe process wants to access the native C++ DLLs and the core VC++ DLLs (msvcr80.dll, mfc80.dll, msvcm80.dll, ...) not in the deployment folder, but in the folders of the PATH environment variable. Now is it possible to convince the ASP.NET application of the DLLs in its deployment folder as well as the VC++ core files deployed in C:\Windows\winsxs? Deployment should be this easy...Contrast
@Contrast maybe its on path for your account that you run, but NOT on the path of the pool account thats run the asp.net ! Fix that on the account that runs the pool.Colvert
@Contrast login, on the pool acount, or just change the setting of the pool acount from the tools of windows.Colvert
I just wonder, why it's searching in PATH and not automatically searching in the bin deployment folder of the ASP.NET application and the C:\Windows\winsxs folder (for the core VC++ DLLs)? I don't want to change the PATH variable on deployment to get this work. Moreover, it's errorprone, since the deployment destination could change. I just want to know if it's possible to get this work without PATH.Contrast
@Contrast where is this dll located ? maybe is not on bin but first found somewhere on c:\WINDOWS\Microsoft.NET\ There are there the Gac directory that maybe have priority. Or maybe this files are loaded all ready by other dll and its diferent version.Colvert
@Contrast This errors need too much time to trace what is loaded first what second etc. Try also the File Monitor, is focus only on files and its fasterColvert
F
5

ProcMon saved me.

The path was my problem too. It seems that IIS is creating a shadow copy of each managed dll in C:\Windows\System32\inetsrv folder. But this in not the case for unmanaged code. When it has to load an unmanaged dll, it search the environmental path and not the bin directory of the application in IIS.

Many thanks Aristos!!

Fighterbomber answered 24/7, 2012 at 9:23 Comment(1)
But how did you solve this issue? Added bin folder to PATH?Sepulture
C
4

Your code reach the _nLoad and this is good because have pass all checks for loading and move to the core to actually load the dll, and there its fail.

For start download the Dependency Walker from http://www.dependencywalker.com/ and use it on dll to find out what other resource this dll needs to run. I suspect that can not load some other dll files.

Additional maybe this dll search for other files that can not find and thats why can not load. The second way is to use the File Monitor, or the Process Monitor from sysinternals to find what fail to load.

http://technet.microsoft.com/en-us/sysinternals
http://technet.microsoft.com/en-us/sysinternals/bb896645

Colvert answered 9/2, 2012 at 9:28 Comment(8)
Thanks at first. I've used Dependency Walker before without finding any problems. I just wonder why the .NET console application with the same deployed assemblies works, while the ASP.NET application fails? That's weird...Contrast
@Contrast as I write, probably because fail to load some resource files. Use also the file monitor to find them out.Colvert
Ok, with ProcMon (first time user) I've gone a step further (thanks!), but hopefully you can explain the results: I saw that the WebDev.WebServer20.exe process wants to access the native C++ DLLs and the core VC++ DLLs (msvcr80.dll, mfc80.dll, msvcm80.dll, ...) not in the deployment folder, but in the folders of the PATH environment variable. Now is it possible to convince the ASP.NET application of the DLLs in its deployment folder as well as the VC++ core files deployed in C:\Windows\winsxs? Deployment should be this easy...Contrast
@Contrast maybe its on path for your account that you run, but NOT on the path of the pool account thats run the asp.net ! Fix that on the account that runs the pool.Colvert
@Contrast login, on the pool acount, or just change the setting of the pool acount from the tools of windows.Colvert
I just wonder, why it's searching in PATH and not automatically searching in the bin deployment folder of the ASP.NET application and the C:\Windows\winsxs folder (for the core VC++ DLLs)? I don't want to change the PATH variable on deployment to get this work. Moreover, it's errorprone, since the deployment destination could change. I just want to know if it's possible to get this work without PATH.Contrast
@Contrast where is this dll located ? maybe is not on bin but first found somewhere on c:\WINDOWS\Microsoft.NET\ There are there the Gac directory that maybe have priority. Or maybe this files are loaded all ready by other dll and its diferent version.Colvert
@Contrast This errors need too much time to trace what is loaded first what second etc. Try also the File Monitor, is focus only on files and its fasterColvert

© 2022 - 2024 — McMap. All rights reserved.