VSIX - Cannot load file or assembly of a referenced dll
Asked Answered
P

1

18

My question is very similar to this one, only that the answer and work-around are not working for me. Also I am in Visual Studio 2012.

I have a VSPackage which is referencing another project, which is dependent on other dlls. Everytime time I run my package in debug I get an exception that the other dlls cannot be found. They are in the output directory, and they are signed.

I tried referencing them directly by the VSPackage project to no avail.

Thoughts?

Panettone answered 2/12, 2012 at 22:47 Comment(0)
W
44

This problem exists because Visual Studio is not looking for assemblies in a folder of your extension if your extension has no explicit dependence on these assemblies. For example, dependences set in a configuration file (IoC config) or in xaml code. I know three solutions to this problem:

  1. You can deploy these assemblies in the GAC and Visual Studio will load them. This method is good if you use a third-party library that built for use in the GAC (for example, MS Enterprise Library). But VSIX Deployment Package does not allow installing assemblies in the GAC, you can use the MSI installer.

  2. For VSPackages for Visual Studio 2010/2012 you can use ProvideBindingPath attribute. The path where your extension located will be added to the paths that Visual Studio uses to find dependent assemblies. If your extension doesn't include a VSPackage, you can add this attribute to any public class (see here).

    [ProvideBindingPath] 
    public class MyVsPackage : Package 
    { /* ... */ }
    
  3. You can manually resolve assembly names. To do this, you need to subscribe to the AssemblyResolve event and you need to return required assemblies from a handler. This is the most flexible way, if you cannot use the previous methods, this is especially for you.

    In my IntelliDebugger project, I wrote a class ManualAssemblyResolver for it:

using System;
using System.Reflection;
    
namespace IntelliEgg.Debugger.Utility
{
    public class ManualAssemblyResolver : IDisposable
    {
        public ManualAssemblyResolver(Assembly assembly)
        {
            if (assembly == null)
                throw new ArgumentNullException("assembly");

            _assemblies = new[] {assembly};
            AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
        }

        public ManualAssemblyResolver(params Assembly[] assemblies)
        {
            if (assemblies == null)
                throw new ArgumentNullException("assemblies");

            if (assemblies.Length == 0)
                throw new ArgumentException("Assemblies should be not empty.", "assemblies");

            _assemblies = assemblies;
            AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
        }

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

        private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
        {
            foreach (Assembly assembly in _assemblies)
            {
                if (args.Name == assembly.FullName)
                {
                    return assembly;
                }
            }

            return null;
        }

        private readonly Assembly[] _assemblies;
    }
}

This class must be created before the first call to the problem assembly (e.g., in Package::Initialize() method)

Wisla answered 7/12, 2012 at 15:15 Comment(4)
How did you load the assemblies to pass into this utility class? Rather... what context did you use? Assembly.LoadFrom(filename)? I am wondering how you protect the same version of an assembly from being loaded by another plugin in another context?Bradlybradman
Yes I use Assembly.LoadFrom() or typeof(ClassFromMyAssembly).Assembly and a reference to MyAssembly in the project (for System.Windows.Interactivity.dll). The purpose of using ManualAssemblyResolver allows Visual Studio to load all dependent assemblies from any folder and explicitly determine it in your code. To support modularity I use MS Prism and configure modules loading in the Bootstrapper class.Wisla
2. Worked for me. Can it bring problems if other extensions also provide the path and use the same libraries?Cuticula
#2 solved my problem in VS2017. It was working without it for years but no it was suddenly required. I don't understand why.Pomfret

© 2022 - 2024 — McMap. All rights reserved.