4

For a .Net C# app that uses SAP.DATA.HANA.v4.5 v2.3.119 and is installed on the runtime machine with the libadonetHDB.dll v2.3.119 with the environment variable HDBADONET pointing to the app folder where libadonetHDB.dll exists. The application works as expected so far on several installations, however one new installation I am seeing it fail producing the The specified module could not be found error exception from HanaConnection below:

The type initializer for 'Sap.Data.Hana.HanaConnection' threw an exception.
System.Exception: The specified module could not be found
   at Sap.Data.Hana.HanaUnmanagedDll.LoadDll(String dllPath)
   at Sap.Data.Hana.HanaUnmanagedDll..ctor()
   at Sap.Data.Hana.HanaUnmanagedDll.get_Instance()
   at Sap.Data.Hana.HanaConnection..cctor()

Also tried just moving the dll to the same folder where the application is installed and the same results are produced.

According to the documentation, the dll being in the same folder as the application or via the HDBADONET environment variable path location should work (and have experienced it working on several other installations). This is part of the general workflow for developing and using the ADO.NET library for non-native .NET apps documented here

I've been trying this as the "Administrator" user and this is a brand new Virtual Machine created (tried both new Windows10 x64 VM and new Windows Server 2016 x64 VM). Also confirmed .NET v4.5+ was installed.

Is it possible that a machine can have a permissions or other policy that affects loading of dlls?

Any clue as to why the SAP Hana ADO.NET DB Connection DLL loading will fail but not in all cases?

Is the libadonetHDB.dll still trying to find and load libSQLDBCHDB.dll or another dll on the machine for some reason? It has been my understanding that using the ADO.NET DLL allowed the machine to not need the other client installation and dlls installed.

Which module is it that can't be found specifically? Is there a way to get the Hana Connection DLL loading to generate more verbose output when it fails?

Update

To confirm that the libadonetHDB.dll is actually found using the HDBADONET environment variable definition, I removed the file and retested and I get a different message:

The type initializer for 'Sap.Data.Hana.HanaConnection' threw an exception.
System.IO.FileNotFoundException: Cannot find a matching libadonetHDB.dll 
with version 2.3.119 - check the location in the HDBADONET or PATH 
environment variables
   at Sap.Data.Hana.HanaUnmanagedDll.SearchNativeDlls()
   at Sap.Data.Hana.HanaUnmanagedDll..ctor()
   at Sap.Data.Hana.HanaUnmanagedDll.get_Instance()
   at Sap.Data.Hana.HanaConnection..cctor()

So, the message posted in the original post is coming after libadonetHDB.dll has been found successfully. So it seems like the complaint in the exception message about unable to find or load a module is referring to some other resource or dll it is looking for, but the message is not verbose enough to know what that is. Any ideas?

Update (the solution)

The short answer:

Inspecting libadonetHDB.dll with Dependencies reveals that msvcr100.dll and msvcp100.dll were both missing on the runtime machine for some reason. Adding those missing DLLs to the app's installation package resolved the issue.

The longer answer:

Thanks to donjuedo for suggesting to interrogate the DLL to see its dependencies. The tool I used on the machine where it was failing is Dependencies (which requires installation of vc++ redistributable x64 as noted in the readme for it to work) revealed that msvcr100.dll and msvcp100.dll were both missing as dependencies when inspecting libadonetHDB.dll. Note that they were only found to be missing on this particular machine which was a freshly created virtual machine so the inspection and test case had to happen on that machine.

The solution for including the missing DLLs at installation time can be to add msvcr100.dll and msvcp100.dll to either of the following locations:

  • C:\Windows\System32 (probably not a preferred solution if you want your app to avoid installing things into the main system folder)
  • the folder where the app's exe also exists
  • an app's lib subfolder so long as you add the path to that subfolder to the PATH environment variable definition (i.e. set PATH=%PATH%;fullpath\to\app\lib)

These two dlls were already on our development machine and are likely already part of many runtime/client machines that have been around a while and have had other software that needed them. If you don't have these around even in development then download them from Microsoft's official packages as noted here (avoid getting them from 3rd party dll websites if you want be sure they aren't malware hiding in a dll). Ideally the documentation for the SAP HanaDB ADO.NET library should mention the requirements of the runtime machine or that the .NET developer needs to provide these dependent DLLs.

Streamline
  • 2,040
  • 4
  • 37
  • 56
  • Have you tried Dependency Walker to see what other DLL your DLL may be trying to load? – donjuedo May 30 '19 at 18:15
  • I haven't. I assume this would get installed on the runtime machine and it monitors the runtime execution of the app? – Streamline May 30 '19 at 18:19
  • That's my understanding of it (it's new to me). In Linux, I can use strace or ktrace to see lots of (noisy) "under the hood" information about what is going on, and it often reveals info I would not have been able to get any other way. This looks similarly useful, but well-focused on DLL's. – donjuedo May 30 '19 at 18:27
  • Also, FWIW, Dependency Walker is free. – donjuedo May 30 '19 at 18:27
  • I tried Dependency Walker but it gives a bunch of false negative feedback and as [noted here](https://stackoverflow.com/a/36244483/56082) I tried another tool called [Dependencies](https://github.com/lucasg/Dependencies) (which first requires installation of vc++ redistributable x64) and it appears to be indicating that `MSVCR100.dll` is missing if I'm interpreting correctly. Why wouldn't this be included when our .NET app is built in Visual Studio? Searching the local runtime machine I do see `msvcr100_clr0400.dll`. Should `msvcr100_clr0400.dll` satisfy the same need that `MSVCR100.dll` does? – Streamline May 31 '19 at 19:00
  • I confirmed that if I add `msvcr100.dll` and `msvcp100.dll` (both identified in [Dependencies](https://github.com/lucasg/Dependencies) as missing when inspecting `libadonetHDB.dll`) to the same folder where our app's .exe file lives on the runtime machine, then the exception goes away! Is there a way to incorporate these dlls into the assembly exe at build time in Visual Studio or to have them be discoverable from a subfolder of the app where we include other dlls so we don't have to include them in the root folder for our app? – Streamline May 31 '19 at 20:29
  • @donjuedo I think your suggestion to use a tool (such as Dependency Walker / Dependencies) to discover the DLL's dependencies (on the machine where it is failing) is pretty much the answer here as far as I can tell. If you create an answer detailing that, I can select it as the answer and award the bounty. If you know how the DLLs can be included in the assembly exe at build time in Visual Studio for a C# .NET solution/project, that would be great. I saw some references to doing static library linking but it wasn't really clear considering the app's project type and these library types. – Streamline May 31 '19 at 23:36
  • Also noting here for future folks that outside of the preferred method of being able to include the DLLs in the assembly exe at build time, the DLLs (`msvcr100.dll` and `msvcp100.dll`) were found by `libadonetHDB.dll` if I added the app's lib subfolder (where they will live along side of `libadonetHDB.dll`) to the `PATH` environment variable which is a little cleaner than including them in the app's root folder. I'll also update the main post with all of these findings. – Streamline May 31 '19 at 23:45

1 Answers1

2

My suggestion is to use Dependency Walker (or other similar util) to determine what DLL the found DLL looking for. It looks like one is found but not all symbol dependencies were satisfied in that case.

Streamline makes a great point: the failure seen was a runtime failure, not a build time failure. Runtime environments vary, so the DLL picked up to satisfy symbols required can be different. Troubleshooting must be done on the particular system experiencing the exception.

donjuedo
  • 2,475
  • 18
  • 28
  • @Streamline, thanks for the update. And I am sorry, but the C# DLL inclusion is beyond me. – donjuedo Jun 01 '19 at 21:12
  • 1
    Ok. For the benefit of future folks maybe edit your answer to note that the inspection of the DLL with a dependency tool has to be on the runtime machine where it is failing in order for it to reveal what is missing in that environment. It is not enough to just know what the dependencies are or inspect the DLL in development, for instance, where it doesn't fail. – Streamline Jun 01 '19 at 21:42