SolvedMaterialDesignInXamlToolkit Could not load file or assembly 'MaterialDesignColors, Culture=neutral' or one of its dependencies

Hi am getting the following error when running my class library project.

"Could not load file or assembly 'MaterialDesignColors, Culture=neutral' or one of its dependencies. The system cannot find the file specified.":"MaterialDesignColors, Culture=neutral"} System.Exception {System.IO.FileNotFoundException

I tried the below link forthe issue Could not load file or assembly 'MaterialDesignThemes.Wpf and the issue got fixed by adding the piece of code suggested as below .

   public partial class UserControl1 : UserControl
    {
        public UserControl1()
        {
            InitializeComponent();
            ShadowAssist.SetShadowDepth(this, ShadowDepth.Depth0);
        }
    }

Is there any fix like above available for `MaterialDesignColors.dll ?

Note : All the dlls exists in same folder.

32 Answers

✔️Accepted Answer

For folks still encountering this issue: this post by Carlos Anderson explains what's going on:

There’s another tricky thing. Because you don’t use any classes in the Material Design assemblies, your script assembly doesn’t load those assemblies. It’s the XAML parser that uses the Material Design assemblies and therefore tries to load them. The problem is that, because it’s not your assembly that loads them, .NET looks for the Material Design assemblies in the wrong place.

And provides a solution similar to what @z3ke1r suggests:

public MainWindow()
{
    InitializeMaterialDesign();
    InitializeComponent();
}
 
private void InitializeMaterialDesign()
{
    // Create dummy objects to force the MaterialDesign assemblies to be loaded
    // from this assembly, which causes the MaterialDesign assemblies to be searched
    // relative to this assembly's path. Otherwise, the MaterialDesign assemblies
    // are searched relative to Eclipse's path, so they're not found.
    var card = new Card();
    var hue = new Hue("Dummy", Colors.Black, Colors.White);
}

This solved it for me.

Other Answers:

Finally found solution.

May be this gonna help someone. Here is it:

public class AssemblyLoader: IDisposable {
 private static string ExecutingPath => Assembly.GetExecutingAssembly().Location;

 public AssemblyLoader() {
  AppDomain.CurrentDomain.AssemblyResolve += LoadMaterialDesign;
 }

 private static Assembly LoadMaterialDesign(object sender, ResolveEventArgs args) {
  if (null == ExecutingPath) return null;
  string assemlyToLoad = string.Empty;

  string GetAssemblyName(string fullName) => fullName.Substring(0, fullName.IndexOf(','));

  var path = ExecutingPath;
  var dir = new FileInfo(path).Directory;

  var assemblies = from file in dir.EnumerateFiles()
  where file.Name.EndsWith(".dll") ||
   file.Name.EndsWith(".exe")
  select Assembly.LoadFrom(file.FullName);

  foreach(var assembly in assemblies) {

   var assemName = GetAssemblyName(assembly.FullName);
   var requested = GetAssemblyName(args.Name);

   try {
    if (assemName == requested) {
     return assembly;
    }
   } catch (Exception) {
    continue;
   }

   //}
  }
  return null;
 }

 void IDisposable.Dispose() {
  AppDomain.CurrentDomain.AssemblyResolve -= LoadMaterialDesign;
 }
}

Usage example:

[Transaction(TransactionMode.Manual)]
public class Command : IExternalCommand
{
	public Result Execute(ExternalCommandData commandData,
						ref string message,
						ElementSet elements)
	{
		using var loader = new AssemblyLoader();
                /// Your command implementation
		return Result.Succeeded();
	}
}

For anyone using this library in a Visual Studio extension, you have to do two things:

  1. Sign the assembly (necessary for all VSIX dependencies). The easiest way is using the StrongNamer package. Just add it to your project as a reference and it will sign all unsigned dependencies at build time. No further setup needed.
  2. Add the [ProvideBindingPath] attribute to extension's Package or AsyncPackage file. This tells your XAML files to look at all the project's references. See here for more details.

Hi,
I encountered the same issue while attempting to load an application.
I built upon @hedinjke's good work by removing unnecessary calls to the Assembly.LoadFrom() method. I noticed that your suggestion would lead to many unnecessary calls - in my case, the same assembly would be loaded 16 times or so.

Instead of using a foreachstructure to iterate over the list of assemblies returned by:

var assemblies = from file in dir.EnumerateFiles()
    where file.Name.EndsWith(".dll") ||
    file.Name.EndsWith(".exe")
    select Assembly.LoadFrom(file.FullName);

I return a list of strings and use LINQ expressions to compare between the assemblies already loaded, and the ones required by the AppDomain.CurrentDomain.AssemblyResolve event.

  • If the assembly is already loaded, we return it, as expected by the event
  • If the assembly is not loaded, and requested and present in the list of files, we return it via return Assembly.LoadFrom(assemblyToLoad);
  • If the assembly is not loaded, and requested, but missing from the build directory, we return null.

AssemblyLoader.cs

using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;

namespace App.Namespace
{
    /// <summary>
    /// Used to determine the UNC path of the solution files (on the file system)
    /// and load the assembly
    /// </summary>
    public class AssemblyLoader : IDisposable
    {
        private static string _executingPath;
        public AssemblyName _assemblyName;

        private DirectoryInfo _fileInfo;
        private IEnumerable<string> _assemblies;

        readonly AppDomain currentDomain = AppDomain.CurrentDomain;

        private IEnumerable<Assembly> _domainAssemblies;

        /// <summary>
        /// Default constructor
        /// </summary>
        public AssemblyLoader()
        {
            // Store the loaded assemblies
            _executingPath = Assembly.GetExecutingAssembly().Location;
            _fileInfo = new FileInfo(_executingPath).Directory;

            // Return a list of all DLLS from the executing directory
            _assemblies = EnumerateFiles.GetFiles(_fileInfo);
            _domainAssemblies = currentDomain.GetAssemblies().Where(a => !a.IsDynamic);

            AppDomain.CurrentDomain.AssemblyResolve += LoadApplicationAssemblies;
        }

        /// <summary>
        /// Event handler to return an assembly
        /// </summary>
        /// <param name="sender">The object that raises the event</param>
        /// <param name="args">Supplementary parameters</param>
        /// <returns>The name of the a assembly</returns>
        public Assembly LoadApplicationAssemblies(object sender, ResolveEventArgs args)
        {
            if (string.IsNullOrEmpty(_executingPath))
                return null;

            try
            {
                // Ignore missing resources
                if (args.Name.Contains(".resources"))
                    return null;

                // Check for assemblies already loaded
                Assembly loadedAssembly = _domainAssemblies.FirstOrDefault(x => x.FullName == args.Name);
                if (loadedAssembly != null)
                    return loadedAssembly;

                var requestedAssembly = args.Name.Split(',')[0];
                var assemblyToLoad = _assemblies.Where(x => x.Contains(requestedAssembly)).FirstOrDefault();

                return Assembly.LoadFrom(assemblyToLoad);
            }

            catch (Exception e)
            {
                // or rethrow the exception
                // throw;
                return null;
            }
        }

        public void Dispose()
        {
            AppDomain.CurrentDomain.AssemblyResolve -= LoadApplicationAssemblies;
        }
    }
}

EnumerateFiles.cs

using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace App.Namespace
{
    /// <summary>
    /// Return a list of DLLs in-use by the project. See the <see cref=AssemblyLoader"/> class
    /// for an example
    /// </summary>
    class EnumerateFiles
    {
        /// <summary>
        /// Return the list of files in fileInfo
        /// </summary>
        /// <param name="fileInfo">The directory</param>
        /// <returns>A read-only enumerable (list) that contains a list of files in use</returns>
        public static IEnumerable<string> GetFiles(DirectoryInfo fileInfo)
        {
            return from file in fileInfo.EnumerateFiles()
                   where (file.Name.EndsWith(".dll") || file.Name.EndsWith(".exe"))
                   select file.FullName;
        }
    }
}

More Issues: