Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to include assemblies from NuGet packages in a VSIX Installer?

I'm working on creating a Visual Studio 2017 custom Check-In Policy extension. My current solution is structured as follows:

VSIX Solution Structure

Note: I am taking advantage of the new NuGet PackageReference approach, which is why there is no packages.config file.


I believe I have setup my VSIX manifest appropriately since everything works perfectly when I don't reference Microsoft.Net.Http (originally I was hard-coding in values instead of retrieving the values). I'm not sure why the Microsoft.TeamFoundationServer.ExtendedClient NuGet package being included doesn't cause any issues, whereas the Microsoft.Net.Http NuGet package does.

I looked at the debug folder to see what is being compiled and I see every assembly necessary being pulled in, however if I unpack the VSIX (I renamed it to *.zip and unzipped it), only the project assembly is included; the Nuget referenced assemblies are not packaged in the VSIX package.

I came across a few resources, but nothing seems to work:

  • VSIX Package doesn't include referenced project's dependencies
  • VSIX with Project Templates and NuGet Packages
  • How to include a Nuget package in a Visual Studio Extension (vsix)
  • VSIX extension - How can I ensure a referenced dll or assembly is included in the VSIX file?

Every single one of these questions/answers do not seem to address my specific problem.


Update:

I believe it is possible that the tool used to generate the VSIX package does not support the new PackageReference feature of NuGet. If I utilize the older packages.config feature, everything works fine. I have put in a UserVoice Ticket to support the new NuGet feature.

like image 694
myermian Avatar asked May 01 '17 20:05

myermian


People also ask

How do I add NuGet package source to Visual Studio?

Set up Visual StudioIn Visual Studio, select Tools, and then select Options. Select NuGet Package Manager, and then select Package Sources. Enter the feed's Name and Source URL, and then select the green (+) sign to add a new package source. If you enabled upstream sources in your feed, clear the nuget.org checkbox.


2 Answers

For those poor guys like us who face this problem (nuget using PackageReference and VSIX dependencies), I found a workaround, inspired by this post: NuGet packages referenced via PackageReference don't include DLLs in VSIX that didn't fully worked for me (it was including the metadata-only version of the assembly, not the full assembly with code). For example, here, I reference 4 nuget packages manually:

<Target Name="IncludeNuGetPackageReferences" AfterTargets="GetVsixSourceItems">
  <ItemGroup>
    <VSIXSourceItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'Microsoft.Win32.Registry'" />
    <VSIXSourceItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'System.CodeDom'" />
    <VSIXSourceItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'System.Configuration.ConfigurationManager'" />
    <VSIXSourceItem Include="@(ReferenceCopyLocalPaths)" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' == 'System.ServiceProcess.ServiceController'" />
  </ItemGroup>
</Target>

PS: Tested with Visual Studio 2017 from 15.5.4 to 15.7.3

like image 164
Simon Mourier Avatar answered Oct 06 '22 19:10

Simon Mourier


I you're looking for a more flexible way to other answers I have used the following.

  <Target Name="IncludeProjectReferenceNuGetPackageAssemblies" AfterTargets="GetVsixSourceItems">
    <!--Add project reference NuGet package assemblies to the package-->
    <ItemGroup>
      <VSIXSourceItem Include="@(ReferencedVSIXSourceItem)" Condition="'%(ReferencedVSIXSourceItem.NuGetSourceType)' == 'Package' and '%(ReferencedVSIXSourceItem.FrameworkFile)' != 'true'" />
    </ItemGroup>
  </Target>

This will add all resolved project reference NuGet references to the appropriate VSIXSubPath. This will also ignore framework references to NuGet package files.

The items are added in the target GetVsixSourceItems. I also had issues adding the project output assembly because by default it adds the assembly in the intermediate output path (obj) folder. This was causing issues for me because I sign the assembly in the bin folder. Here's a target to use the bin assembly instead of the intermediate output assembly.

  <Target Name="SwapIntermediateAssemblyForTargetPath" AfterTargets="GetVsixSourceItems" Condition="'$(IncludeAssemblyInVSIXContainer)' == 'true'">
    <!--Create an item for the primary output of the project. By default the intermediate assembly is packed in the VSIX. Use the output target path instead.-->
    <ItemGroup>
      <VSIXSourceItem Remove="@(IntermediateAssembly)" />

      <VSIXSourceItem Include="$(TargetPath)">
        <VSIXSubPath>$(AssemblyVSIXSubPath)</VSIXSubPath>
        <InstallRoot>$(InstallRoot)</InstallRoot>
        <Ngen>$(Ngen)</Ngen>
        <NgenApplication>$(NgenApplication)</NgenApplication>
        <NgenArchitecture>$(NgenArchitecture)</NgenArchitecture>
        <NgenPriority>$(NgenPriority)</NgenPriority>
      </VSIXSourceItem>
    </ItemGroup>
  </Target>
like image 28
Manny Avatar answered Oct 06 '22 19:10

Manny