Problem with case sensitivity (dll vs DLL) on Windows
I got this backtrace when running dotnet ef database update on a Core 3.1 app:
---> System.DllNotFoundException: Unable to load DLL 'e_sqlite3' or one of its dependencies: The specified module could not be found. (0x8007007E)
at System.Runtime.InteropServices.NativeLibrary.LoadByName(String libraryName, QCallAssembly callingAssembly, Boolean hasDllImportSearchPathFlag, UInt32 dllImportSearchPathFlag, Boolean throwOnError)
at System.Runtime.InteropServices.NativeLibrary.LoadLibraryByName(String libraryName, Assembly assembly, Nullable`1 searchPath, Boolean throwOnError)
at System.Runtime.InteropServices.NativeLibrary.Load(String libraryName, Assembly assembly, Nullable`1 searchPath)
at SQLitePCL.NativeLibrary.Load(String libraryName, Assembly assy, Int32 flags)
at SQLitePCL.Batteries_V2.MakeDynamic(String name, Int32 flags)
at SQLitePCL.Batteries_V2.DoDynamic_cdecl(String name, Int32 flags)
at SQLitePCL.Batteries_V2.Init()
From tracing the command, it appears it was looking for C:\Users\username\Projects\projectname\bin\Debug\netcoreapp3.0\runtimes\win-x64\native\e_sqlite3.DLL - which didn't exist, so it was failing.
However, e_sqlite3.dll did exist. I copied it, and uppercased the extension - everything then started working again.
I'm not quite sure how I got it into this state (it was a fresh git checkout, dotnet restore, etc.)!
I can reproduce this problem on Windows with .NET Core SDK 3.1.201 when using a case-sensitive directory:
- Create a new directory and make it case-sensitive (requires Windows 10 Version 1803 or higher, and requires the Windows Subsystem for Linux (WSL) to be enabled in Windows Features):
mkdir "%USERPROFILE%\TestSqlite"
fsutil.exe file setCaseSensitiveInfo "%USERPROFILE%\TestSqlite" enable
- Create a new .NET Core 3.1 app:
cd "%USERPROFILE%\TestSqlite"
dotnet new console
dotnet add package SQLitePCLRaw.bundle_e_sqlite3 --version 2.0.2
- Change
Program.csto the following code:
class Program
{
static void Main()
{
SQLitePCL.Batteries_V2.Init();
}
}
- Run the program with
dotnet run:
C:\Users\developer4\TestSqlite>dotnet run
Unhandled exception. System.DllNotFoundException: Unable to load DLL 'e_sqlite3' or one of its dependencies: The specified module could not be found. (0x8007007E)
at System.Runtime.InteropServices.NativeLibrary.LoadByName(String libraryName, QCallAssembly callingAssembly, Boolean hasDllImportSearchPathFlag, UInt32 dllImportSearchPathFlag, Boolean throwOnError)
at System.Runtime.InteropServices.NativeLibrary.LoadLibraryByName(String libraryName, Assembly assembly, Nullable`1 searchPath, Boolean throwOnError)
at System.Runtime.InteropServices.NativeLibrary.Load(String libraryName, Assembly assembly, Nullable`1 searchPath)
at SQLitePCL.NativeLibrary.Load(String libraryName, Assembly assy, Int32 flags)
at SQLitePCL.Batteries_V2.MakeDynamic(String name, Int32 flags)
at SQLitePCL.Batteries_V2.DoDynamic_cdecl(String name, Int32 flags)
at SQLitePCL.Batteries_V2.Init()
at Program.Main() in C:\TestSqlite\Program.cs:line 5
When going into the folder bin\Debug\netcoreapp3.1\runtimes\win-x64\native and renaming e_sqlite3.dll to e_sqlite3.DLL, the exception no longer occurs.
I think the exception can be fixed by specifying the exact file name to NativeLibrary.Load (e_sqlite3.dll rather than e_sqlite3), as apparently LoadLibraryW appends .DLL (rather than .dll) when the file extension is omitted.
Thanks!
When using Docker with Windows Subsystem for Linux, this isn't so much an edge-case anymore. The recommendation is to keep files needed for containers in the Linux file system, which is case-sensitive, even though we're still running our IDE (JetBrains Rider in this case) on Windows.
Renaming the file from e_sqlite3.dll to e_sqlite3.DLL does indeed solve the issue, would it be possible to either change the file name or the call to NativeLibrary.Load as suggested above?
I do agree that I need some kind of a fix here.