Include external .dll in Visual Studio Extension

泄露秘密 提交于 2019-12-13 07:41:35

问题


I have a problem using external libraries for my visual studio extension. Currently I have my own NuGet server on which I host my libraries, now since I dont want functionality twice I extracted some functions out of my extension into an existing library.

The problem is however that whenever I want to use anything from that assembly I can not do so, since visual studio does not include the .dlls in the .vsix package.

So far I have tried:

  1. using Assets to include the libraries from their package location. This creates two items in the solution which also have their "Include in VSIX" property set to true, this did not work
  2. including the projects and then adding the BuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;SatelliteDllsProjectOutputGroup; to the "Other Groups included in VSIX" property of the reference, which did not work
  3. using Assets to include the libraries as projects, which did not work

So now I am at my end since there is nothing that seems to work....

The solutions I found are already suggesting all the steps I tried, but at this point

I also found these two post which are the same as my question but those answerts did not work for me like I said.

this

this


回答1:


Okay I found a way to do it, its a combonation of two answers I found here on stack overflow.

And eventhough its a bit hacky I suppose its the only way possible.

So I simply used the existing ManualAssemblyResolver and adjusted it to my needs, the Result being this:

public class ManualAssemblyResolver : IDisposable
{
    #region Attributes

    /// <summary>
    /// list of the known assemblies by this resolver
    /// </summary>
    private readonly List<Assembly> _assemblies;

    #endregion

    #region Properties

    /// <summary>
    /// function to be called when an unknown assembly is requested that is not yet kown
    /// </summary>
    public Func<ResolveEventArgs, Assembly> OnUnknowAssemblyRequested { get; set; }

    #endregion

    #region Constructor

    public ManualAssemblyResolver(params Assembly[] assemblies)
    {
        _assemblies = new List<Assembly>();

        if (assemblies != null)
            _assemblies.AddRange(assemblies);

        AppDomain.CurrentDomain.AssemblyResolve += OnAssemblyResolve;
    }

    #endregion

    #region Implement IDisposeable

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

    #endregion

    #region Private

    /// <summary>
    /// will be called when an unknown assembly should be resolved
    /// </summary>
    /// <param name="sender">sender of the event</param>
    /// <param name="args">event that has been sent</param>
    /// <returns>the assembly that is needed or null</returns>
    private Assembly OnAssemblyResolve(object sender, ResolveEventArgs args)
    {
        foreach (Assembly assembly in _assemblies)
            if (args.Name == assembly.FullName)
                return assembly;

        if (OnUnknowAssemblyRequested != null)
        {
            Assembly assembly = OnUnknowAssemblyRequested(args);

            if (assembly != null)
                _assemblies.Add(assembly);

            return assembly;
        }

        return null;
    }

    #endregion
}

After that I used an Addition ExtensionManager to get the installation path of the extension. Which looks like this

public class ExtensionManager : Singleton<ExtensionManager>
{
    #region Constructor

    /// <summary>
    /// private constructor to satisfy the singleton base class
    /// </summary>
    private ExtensionManager()
    {
        ExtensionHomePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments), Definitions.Constants.FolderName);

        if (!Directory.Exists(ExtensionHomePath))
            Directory.CreateDirectory(ExtensionHomePath);

        SettingsFileFullname = Path.Combine(ExtensionHomePath, Definitions.Constants.SettingsFileName);

        InstallationPath = Path.GetDirectoryName(GetType().Assembly.Location);
    }

    #endregion

    #region Properties

    /// <summary>
    /// returns the installationPath
    /// </summary>
    public string InstallationPath { get; private set; }

    /// <summary>
    /// the path to the directory where the settings file is located as well as the log file
    /// </summary>
    public string ExtensionHomePath { get; private set; }

    /// <summary>
    /// the fullpath to the settingsfile
    /// </summary>
    public string SettingsFileFullname { get; private set; }

    #endregion
}

Then in the Initialize() method of the Package you will need to create an instance of the ManualAssemblyResolver and provide the Path to the assemblies you need like this:

    #region Attributes

    private ManualAssemblyResolver _resolver;

    #endregion

    #region Override Microsoft.VisualStudio.Shell.Package

    /// <summary>
    /// Initialization of the package; this method is called right after the package is sited, so this is the place
    /// where you can put all the initialization code that rely on services provided by VisualStudio.
    /// </summary>
    protected override void Initialize()
    {
        _resolver = new ManualAssemblyResolver(
        Assembly.LoadFrom(Path.Combine(ExtensionManager.Instance.InstallationPath, Definitions.Constants.NameOfAssemblyA)),
        Assembly.LoadFrom(Path.Combine(ExtensionManager.Instance.InstallationPath, Definitions.Constants.NameOfAssemblyB))
        );

Note that you will need to call this before anythingelse that even touches anything from the referenced assemblies, otherwise a FileNotFoundException will be thrown.

In any case this seems to work for me now but I wish there was a cleaner way to do it. So if anybody has a better way (a way that actually includes and lloks up the assemblies from the .vsix package) then please post an answer.

EDIT: Okay now I found the real issue, it was simply the fact that the dlls were satellite dll (the had their assembly culture set) so they were not visible....

However the above fix worked when they were still satillite dlls.



来源:https://stackoverflow.com/questions/32811083/include-external-dll-in-visual-studio-extension

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!