2015-09-27 64 views
0

我的Visual Studio擴展使用外部庫時出現問題。目前,我有我自己的NuGet服務器,我承載我的庫,現在因爲我不需要功能兩次,我從我的擴展中提取了一些功能到現有的庫。在Visual Studio擴展中包含外部.dll

但問題是,無論何時我想使用該程序集中的任何內容,我都無法這樣做,因爲Visual Studio不包含.vsix包中的.dll。

到目前爲止,我曾嘗試:

  1. 使用的資產,包括從他們的包位置的庫。這在解決方案中創建了兩個項目,它們的「Include in VSIX」屬性設置爲true,這不起作用
  2. 包括項目,然後添加BuiltProjectOutputGroup; BuiltProjectOutputGroupDependencies; GetCopyToOutputDirectoryItems; SatelliteDllsProjectOutputGroup;以「其他組包含在VSIX」的提法,這不以資產爲包括庫,項目,工作
  3. 的屬性,它並沒有在我的工作結束

所以現在的我因爲有沒有什麼似乎工作....

我發現已經建議所有我試過的步驟,但在這一點

我也發現了這兩個帖子裏面是一樣的,我的問題,但這些answerts的解決方案沒有像我說的那樣爲我工作。

this

this

+0

嗯,我的水晶球說,包括的DLL都很好,VS只是找不到它們。 [閱讀此](http://stackoverflow.com/questions/13674782/vsix-cannot-load-file-or-assembly-of-a-referenced-dll)。 –

+0

是的,我知道他們包括我得到一個FileNotFoundException,唯一的問題是,我怎麼解決這個問題,因爲沒有任何帖子爲我工作。第三個選項對我來說不是工作,或者btw,每當我在初始化包中初始化ManualAssemblyResolver時,甚至不能創建包。 – DokutoMekki

回答

0

好吧,我發現了一個辦法做到這一點,它的兩個答案的combonation我發現這裏的堆棧溢出。

而且儘管它有點冒失,但我認爲它是唯一可行的方法。

所以我只是用現有的ManualAssemblyResolver,它適應了我的需求,其結果是這樣的:

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 
} 

後,我用了一個加ExtensionManager得到擴展的安裝路徑。它看起來像這樣

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 
} 

然後在包的初始化()方法,您將需要創建ManualAssemblyResolver的實例,並提供你需要像這樣的路徑組件:

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

請注意,您需要在anythingelse之前調用它,甚至可以觸及引用程序集中的任何內容,否則將引發FileNotFoundException。

在任何情況下,這似乎現在對我來說,但我希望有一個更乾淨的方式來做到這一點。因此,如果有人有更好的方法(實際上包含並從.vsix包中提取程序集的方法),那麼請發佈答案。

編輯: 好吧,現在我找到了真正的問題,它只是使的DLL附屬DLL(該有自己的組裝文化集),所以他們不可見....事實

然而上述修復工作時,他們仍然satillite DLL。

+0

什麼是「dll衛星dll(有他們的組裝文化集),所以他們不可見....」是什麼意思? – kchoi

+0

這意味着它是一個dll,只有當您的語言環境(基本上是您的操作系統的系統語言)與它相對應時纔會加載該dll。所以在我的情況下,我有一個德國操作系統,但衛星dll基於英語區域設置。因此我無法在我的系統上加載它。實質上,staellite dll是本地化的資源,請參閱http://stackoverflow.com/questions/1123758/what-is-the-difference-between-a-resource-file-and-a-satellite-dll – DokutoMekki