本文介绍了在 Visual Studio 扩展中包含外部 .dll的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 Visual Studio 扩展使用外部库时遇到问题.目前我有自己的 NuGet 服务器,我在上面托管我的库,现在因为我不想要功能两次,所以我从扩展中提取了一些功能到现有库中.

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.

然而,问题是,每当我想使用该程序集中的任何内容时,我都无法这样做,因为 Visual Studio 不包含 .vsix 包中的 .dll.

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. 使用资产从其包位置包含库.这会在解决方案中创建两个项目,它们的包含在 VSIX"属性设置为 true,这不起作用
  2. 包括项目,然后添加 BuiltProjectOutputGroup;BuiltProjectOutputGroupDependencies;GetCopyToOutputDirectoryItems;SatelliteDllsProjectOutputGroup;参考的VSIX 中包含的其他组"属性,这不起作用
  3. 使用 Assets 将库作为项目包含在内,这不起作用

所以现在我结束了,因为似乎没有任何工作......

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.

这个

这个

推荐答案

好的,我找到了一种方法,这是我在堆栈溢出时找到的两个答案的组合.

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.

所以我只是使用了现有的 ManualAssemblyResolver 并根据我的需要对其进行了调整,结果如下:

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
}

之后我使用了一个Addition ExtensionManager来获取扩展的安装路径.看起来像这样

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
}

然后在包的 Initialize() 方法中,您将需要创建 ManualAssemblyResolver 的一个实例,并提供您需要的程序集的路径,如下所示:

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))
        );

请注意,您需要在任何其他甚至涉及引用程序集中的任何内容之前调用它,否则将抛出 FileNotFoundException.

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

无论如何,这现在似乎对我有用,但我希望有一种更干净的方法来做到这一点.因此,如果有人有更好的方法(一种实际上包含并从 .vsix 包中提取程序集的方法),请发布答案.

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.

好的,现在我发现了真正的问题,只是因为 dll 是卫星 dll(设置了它们的程序集文化)所以它们不可见......

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....

但是,当它们仍然是卫​​星 dll 时,上述修复程序有效.

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

这篇关于在 Visual Studio 扩展中包含外部 .dll的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

09-03 11:10