NAudio - Could not load an assembly or one of its dependencies: Naudio.Core

76 Views Asked by At

I'm new to C#. I have a project where I use NAudio package to play sounds. Inside this project, I use CodeDom to compile another program, which is using NAudio too, to play sounds by itself. Now, while the main program is using NAudio without any problem, the CodeDom program is throwing a System.IO.FileNotFoundException when creating an instance of a type containing 2 fields of types NAudio.Wave.IWavePlayer and NAudio.Wave.AudioFileReader. The exception thrown is:

System.TypeInitializationException: System.IO.FileNotFoundException: Could not load file or assembly 'NAudio.Core, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41' or one of its dependencies. The system cannot find the file specified.

This is the code of the type that its initialization throws this exception:

public sealed class Sound
{
    public static readonly List<Sound> sounds = new List<Sound>();

    public string name;
    private string FilePath = null;
    public string filePath
    {
        get
        {
            return FilePath;
        }
        set
        {
            FilePath = value;
            if (soundPlayer != null)
                soundPlayer.Dispose();
            if (reader != null)
                reader.Dispose();
        }
    }
    public bool isPlaying { get; private set; }
    private IWavePlayer soundPlayer = null;
    private AudioFileReader reader = null;

    public Sound(string name, string filePath)
    {
        this.name = name;
        this.filePath = filePath;
        sounds.Add(this);
    }

    public void Play(bool looping = true)
    {
        if (soundPlayer == null)
        {
            if (filePath == null)
                throw new Exception("Audio file path is null");
            soundPlayer = new WaveOut();
            reader = new AudioFileReader(filePath);
            soundPlayer.Init(reader);
        }

        soundPlayer.Play();
        if (looping)
        {
            soundPlayer.PlaybackStopped += (s, e) =>
            {
                Play(false);
            };
        }
        isPlaying = true;
    }

    public void Stop()
    {
        if (soundPlayer != null && soundPlayer.PlaybackState == PlaybackState.Playing)
            soundPlayer.Stop();
        isPlaying = false;
    }

    public static Sound FindByName(string name)
    {
        foreach (Sound sound in sounds)
        {
            if (sound.name == name)
                return sound;
        }
        return null;
    }
}

And this is the code of the CodeDom compilation process:

List<string> compileSources = new List<string>();
...

// create a code provider
CSharpCodeProvider codeProvider = new CSharpCodeProvider();

// create a compiler parameters object and set the output file name
CompilerParameters compilerParams = new CompilerParameters();
compilerParams.GenerateExecutable = true;
string exePath = savePath == null ? masterPath + @"\debug.exe" : savePath;
compilerParams.OutputAssembly = exePath;
List<string> assemblies = new List<string>
{
    // we only want the assembly, the class does not matter
    System.Reflection.Assembly.GetAssembly(typeof(System.Linq.Expressions.Expression)).Location,
    System.Reflection.Assembly.GetAssembly(typeof(System.Random)).Location,
    System.Reflection.Assembly.GetAssembly(typeof(System.IDisposable)).Location,
    System.Reflection.Assembly.GetAssembly(typeof(System.IO.Stream)).Location,
    System.Reflection.Assembly.GetAssembly(typeof(System.Windows.Forms.Form)).Location,
    System.Reflection.Assembly.GetAssembly(typeof(System.Drawing.Bitmap)).Location,
    System.Reflection.Assembly.GetAssembly(typeof(System.Linq.Enumerable)).Location,
    System.Reflection.Assembly.GetAssembly(typeof(System.ComponentModel.AddingNewEventArgs)).Location,
    System.Reflection.Assembly.Load("netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51").Location
};

// load NAudio NuGet package assemblies
Type[] NAudio_assemblies_types = new Type[] {
    typeof(NAudio.Wave.AudioFileReader),
    typeof(NAudio.Wave.WaveStream),
    typeof(NAudio.Wave.WaveOut)
};
foreach (Type type in NAudio_assemblies_types)
{
    string location = System.Reflection.Assembly.GetAssembly(type).Location;
    if (!assemblies.Contains(location))
        assemblies.Add(location);
}
compilerParams.ReferencedAssemblies.AddRange(assemblies.ToArray());

// compile the code

CompilerResults results = codeProvider.CompileAssemblyFromSource(compilerParams, compileSources.ToArray());

I made this test to locate the bad assembly or dependency:

bool cancel = false;
int total = 0, fail = 0;
void ScanAssembly(System.Reflection.Assembly assembly)
{
    if (cancel) return;
    foreach (var dep in assembly.GetReferencedAssemblies())
    {
        if (!File.Exists(dep.CodeBase))
        {
            
            MessageBox.Show("file not found: " + dep.FullName + ": \n" + dep.CodeBase);
            fail++;
        }
        else
        {
            ScanAssembly(System.Reflection.Assembly.Load(dep.Name));
        }
        total++;
    }
}
var core = System.Reflection.Assembly.Load("NAudio.Core, Version=2.2.1.0, Culture=neutral, PublicKeyToken=e279aa5131008a41");
ScanAssembly(core);
MessageBox.Show($"scan complete\n{fail} / {total} fails");

the result: there was only 1 instance in the first foreach loop (in the list returned by assembly.GetReferencedAssemblies()) ran on the core Assembly instance, and its CodeBase was an empty string. Its FullName was "netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51". The content of the message box in the end of the code was: "scan complete. 1 / 1 fails".

Thanks in advance.

0

There are 0 best solutions below