MVC4 App "Unable to load DLL 'libmp3lame.32.dll'
Asked Answered
E

4

7

I am trying to use the NAudio.Lame library in an MVC4 application and am getting the error:

Unable to load DLL 'libmp3lame.32.dll': The specified module could not be found.

I added the library via NuGet. I was able to get the library to work fine with a Windows Forms application, so I believe the problem is specific to MVC4.

I tried the advice from the library author here: https://mcmap.net/q/754114/-system-io-filenotfoundexception-could-not-load-file-or-assembly-39-lamedllwrap-version-1-0-0-0

Emulate answered 20/11, 2013 at 6:13 Comment(1)
Ah, there you are :) Answer coming...Thionate
T
16

The problem turns out to be that the native DLLs (libmp3lame.32.dll and libmp3lame.64.dll) cannot be found because the current directory that the web server process is executing from is not the website's bin folder (where the DLLs reside) and the search path does not include the bin folder.

What you need is to add the bin folder to the PATH environment variable, which will enable the LoadLibrary API call to locate the DLLs.

Here's a method you can call that will do this for you:

public static void CheckAddBinPath()
{
    // find path to 'bin' folder
    var binPath = Path.Combine(new string[] { AppDomain.CurrentDomain.BaseDirectory, "bin" });
    // get current search path from environment
    var path = Environment.GetEnvironmentVariable("PATH") ?? "";

    // add 'bin' folder to search path if not already present
    if (!path.Split(Path.PathSeparator).Contains(binPath, StringComparer.CurrentCultureIgnoreCase))
    {
        path = string.Join(Path.PathSeparator.ToString(), new string[] { path, binPath });
        Environment.SetEnvironmentVariable("PATH", path);
    }
}

Place that in your controller and call it right before you create the LameMP3FileWriter instance. It might work if you put it in Global.asax.cs and call it from Application_Start(). Try it and let me know if it works there.

I've put a Wiki article about this on the project site here.

Thionate answered 20/11, 2013 at 6:24 Comment(5)
This fails with SecurityException when you run your application in mediumTrust. Is there a better way?Amberlyamberoid
@llapinski I've not had to deal with Medium Trust execution, so not sure what effect it has. Where does the above fail? Are you able to edit the PATH environment variable or copy the relevant native DLL to somewhere on the PATH?Thionate
You can't event read path otherwise it throws SecurityException with message "Request for the permission of type 'System.Security.Permissions.EnvironmentPermission, mscorlib, Version=4.0.0.0. I don't yet know if client will be able to edit path on his hosting. Is that workaround. Just add bin location to path manually? IIS does not copy it to some temporary location?Amberlyamberoid
@llapinski Yes, you can edit the path manually to add the project's bin folder, or move the native DLLs to a folder on the path. Either should work. Unfortunately you can't load them from memory like you can do with .NET assemblies.Thionate
This helped with my Azure deployment.Mareld
T
2

Add the following line to the web.config for your site. This will prevent IIS from copying files and executing your site from a temporary folder (native dlls do not get copied apparently). The downside is that you will have to restart the application pool every time you push changes to your bin folder because IIS will lock the files there.

<system.web>
    <hostingEnvironment shadowCopyBinAssemblies="false" />
    ...
</system.web>
Tainataint answered 30/9, 2014 at 3:9 Comment(1)
+1d this answer but it has it's own problems. If you disable shadow copies, VS will lock that dlls and building the project will be pain in the butt since it will not acquire the lock it will get access denied exception when buildingAmbivert
K
1

Most probably IIS just can't find native dlls. Be sure to place native dll files into one of Windows DLL search path locations.

Kill answered 20/11, 2013 at 6:18 Comment(0)
T
0

I made it work by having the LameDLLWrap assembly as a separate one, rather than embedding it in the main assembly. Since I know that my target system is 32 bit, I can afford having a single assembly -- this is simpler for me than playing with PATH on the hoster's machine.

Here's what I did:

  1. Cloned the source
  2. Checkout the Experimental branch
  3. Removed the embedded assemblies from the main project
  4. Set the reference to the wrapper to Copy Local
  5. Recompiled everything
Trainer answered 18/1, 2016 at 10:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.