Library load problems when containerizing a .NET Framework 4.8 application

Docker Desktop Version: 4.16.9
OS: Windows 10 Pro Version 21H2, OS Build 19044.1620.
Development IDE: Visual Studio 2022 Version 4.8.09037

Most of the libraries in my application are implemented in C#, but there are a handful of C++ legacy projects.
I’ve run into a roadblock concerning a C++ library required by this application.

When I attempt to run the application in Visual Studio, one particular library fails to load, giving the following error:

[FileNotFoundException: Could not load file or assembly 'Pure.Util.Drawing.Jpeg.DLL' or one of its dependencies. The specified module could not be found.]
   System.Reflection.RuntimeAssembly._nLoad(AssemblyName fileName, String codeBase, Evidence assemblySecurity, RuntimeAssembly locationHint, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +0
   System.Reflection.RuntimeAssembly.InternalLoadAssemblyName(AssemblyName assemblyRef, Evidence assemblySecurity, RuntimeAssembly reqAssembly, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean throwOnFileNotFound, Boolean forIntrospection, Boolean suppressSecurityChecks) +232
   System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, IntPtr pPrivHostBinder, Boolean forIntrospection) +113
   System.Reflection.RuntimeAssembly.InternalLoad(String assemblyString, Evidence assemblySecurity, StackCrawlMark& stackMark, Boolean forIntrospection) +23
   System.Reflection.Assembly.Load(String assemblyString) +35
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +49

[ConfigurationErrorsException: Could not load file or assembly 'Pure.Util.Drawing.Jpeg.DLL' or one of its dependencies. The specified module could not be found.]
   System.Web.Configuration.CompilationSection.LoadAssemblyHelper(String assemblyName, Boolean starDirective) +762
   System.Web.Configuration.CompilationSection.LoadAllAssembliesFromAppDomainBinDirectory() +259
   System.Web.Configuration.CompilationSection.LoadAssembly(AssemblyInfo ai) +167
   System.Web.Compilation.BuildManager.GetReferencedAssemblies(CompilationSection compConfig) +238
   System.Web.Compilation.BuildManager.GetPreStartInitMethodsFromReferencedAssemblies() +78
   System.Web.Compilation.BuildManager.CallPreStartInitMethods(String preStartInitListPath, Boolean& isRefAssemblyLoaded) +334
   System.Web.Compilation.BuildManager.ExecutePreAppStart() +178
   System.Web.Hosting.HostingEnvironment.Initialize(ApplicationManager appManager, IApplicationHost appHost, IConfigMapPathFactory configMapPathFactory, HostingEnvironmentParameters hostingParameters, PolicyLevel policyLevel, Exception appDomainCreationException) +746

[HttpException (0x80004005): Could not load file or assembly 'Pure.Util.Drawing.Jpeg.DLL' or one of its dependencies. The specified module could not be found.]
   System.Web.HttpRuntime.FirstRequestInit(HttpContext context) +552
   System.Web.HttpRuntime.EnsureFirstRequestInit(HttpContext context) +122
   System.Web.HttpRuntime.ProcessRequestNotificationPrivate(IIS7WorkerRequest wr, HttpContext context) +737

I’ve verified that this DLL file exists and is installed in the proper place with the other binary files and also that it gets installed in the “bin” folder of the container. Therefore I assume that the problem is that I’ve omitted some necessary dependency or that this dependency file is the wrong version. The library in question is built with the platform toolset for Visual Studio 2022 (v143).
My first attempt was to add install the C++ runtime using the following statement in the Dockerfile:

# Visual C++ Multithreaded Runtime DLLs (vcruntime140.dll)
RUN [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; \
	Invoke-WebRequest "https://aka.ms/vs/17/release/vc_redist.x64.exe" -OutFile ".\vc_redist.x64.exe"; \
	Start-Process -filepath .\vc_redist.x64.exe -ArgumentList "/install", "/passive", "/norestart" -Passthru | Wait-Process; \
    Remove-Item -Force .\vc_redist.x64.exe;

Since that didn’t fix the problem, I looked through the project’s dependencies and compared them to the files that were already in Docker/publish. I saw that the file windowsbase.dll was
referenced but not present in Docker/publish, so I added it manually. I still encountered the same load error.

Finally, I enabled Fusion logger and ran the application normally in windows. The log indicated that the following files need to be loaded:
mscorlib.dll version 4.0.0.0
netstandard.dll 2.0.0.0
I’ve also added in these DLLs, again with no success. I’m not certain I have the right file version. I do know that Docker attempts to open netstandard because when I accidentally included a .Net Core version of netstandard, the error changed to:

Could not load file or assembly 'netstandard' or one of its dependencies. Strong name signature could not be verified.  The assembly may have been tampered with, or it was delay signed but not fully signed with the correct private key. (Exception from HRESULT: 0x80131045)

This reverted to the “Could not load file or assembly” error when I replaced netstandard with a (supposedly) compatible version.
Is there any way to determine what file(s) I’m still missing? Or could there be another problem?

I am not a dotNET developer so my reply is based on Linux experiences. Is it possible that the libraries could be in multiple folders and you added the ddl files to another folder?

Docker images doesn’t have everything that a normal operating system has so sometimes, even in case of Linux containers, we need find the missing libraries. To do that we need to know the operating system or the application well enough so we can use the best method to find the libraries. I don’t know what is it in case of Wiindows. I found fusion logger too on Google, but that’s all.

One idea that comes to my mind is using a virtual machine temporarily only until you install the application and find the installed files, libraries and compare them to the container’s filesystem.

Thanks for your prompt response!
I’m assuming you’re correct that we’re still missing some component(s).
As for location, when I browse the container, I see only two places for executables, “libraries” and “bin”. The former is where the C++ runtime libraries kernel32, ucrtbase, and vctruntime140 are installed. Everything else ends up in “bin.” I tried manually copying the contents of “libraries” into “bin” but it didn’t fix the load error.
Our application does work in a virtual machine (our target is a VM instance on Google cloud) which makes it possible to test. But we will require Docker containerization to scale our service up and down to adjust for demand.
All I know for certain is that when I stub out a handful of C++ libraries including this one, the application does load and run in Docker. Unfortunately, this application requires those C++ libraries to perform its function. It would be a major effort to port them to C#.