Excel-DNA/ExcelDna

How to use native libraries when targeting .NET Framework 4.8?

altso opened this issue · 2 comments

altso commented

With the latest version of ExcelDna 1.7-rc5 (or even earlier) it is possible to pack native dependencies in a .dna file, but I could not figure out a way to use them in .NET Framework 4.8.

I am using SQLitePCLRaw and e_sqlite3.dll native library. My understanding is that it uses DllImport or similar mechanism to make calls to the native library. The problem is that even though the library is packed and shipped in .dna file, the process still fails with System.DllNotFoundException: Unable to load DLL 'e_sqlite3': The specified module could not be found. (Exception from HRESULT: 0x8007007E). I verified the content of .dna file and see the library there, so it's not related to the packing process.

Does ExcelDna unpack native libraries to a folder when it loads? I know it loads all managed libraries from memory (opposed to file system), but do not know how native libraries are supposed to be handled/loaded. I could not find any examples in Samples repo as well.

Any help is greatly appreciated.

govert commented

I think we only implemented this for .NET 6. As you suggest, we unpack to a temp directory.
Under .NET 6 there is a built-in resolution mechanism where the native libraries can be easily loaded, so it was tempting and a bit easier to implement. For .NET Framework one could make some plans, but we've not done so in the current version.
If you wanted to do something yourself, you'd either have to take some chunks of the code for the resource extraction and decompression, and implement in your own add-in. Simpler might be to put the native libraries into resources of your own managed library, extract at runtime and call LoadLibrary before any P/Invoke calls from your code.

altso commented

Thank you for the info. I believe you are talking about LoadUnmanagedDllFromPath which is indeed .NET Core only.

[MethodImpl(MethodImplOptions.Synchronized)]
internal static string NativeLibraryResolve(string unmanagedDllName)
{
#if NETCOREAPP
byte[] dllBytes = GetResourceBytes(unmanagedDllName.ToUpperInvariant(), 5);
if (dllBytes == null)
return null;
string dllPath = Path.Combine(tempDirPath, unmanagedDllName);
if (!File.Exists(dllPath))
{
Directory.CreateDirectory(tempDirPath);
File.WriteAllBytes(dllPath, dllBytes);
}
return dllPath;
#else
return null;
#endif
}