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

4

18

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:

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.

Mystical answered 1/5, 2017 at 20:29 Comment(2)
I might come late but this thread solved my problem: #42202423Pyszka
@AmauryLevé: That question may have solved your problem, but it is completely unrelated to the issue that I was referencing, which had to do with the VSIX packager automatically include assemblies through NuGet's PackageReference feature. That question/answer deals with adding assets by referencing the assemblies directly.Mystical
S
5

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

Scharaga answered 19/1, 2018 at 14:10 Comment(0)
E
2

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>
Exaction answered 17/4, 2020 at 22:54 Comment(0)
R
0

I was able to successfully include NuGet packages in a template by performing the steps outlined in the following Microsoft tutorial: Packages in Visual Studio templates

SDKs that are installed using an MSI can install NuGet packages directly on the developer's machine. This makes them immediately available when a project or item template is used, rather than having to extract them during that time. ASP.NET templates use this approach.

I have seen others experiencing problems because of the NuGet packages they are using. For .NET Core, I have used Microsoft.Net.Http, although it does require Microsoft.BCL. Unless you are experiencing problems, I suggest leaving legacy systems as-is, especially since these namespaces seem to be moving targets.

It appears System.Net.Http is the correct choice, at least for .NET on the Windows platform. It is also worth nothing that this package has no external dependencies.


EDIT: It appears this could be related to bugs with PackageReference itself. I see a similar documented bug described here.

Rommel answered 26/5, 2017 at 14:34 Comment(7)
I think you misunderstood the issue I am having. I am not creating Item or Project templates, but instead a custom Check-In Policy. The problem I ran into is that the VSIX package generated did not include the NuGet assemblies that my assembly depended on. The link you are referencing is how to ensure that Item/Project templates automatically pull in NuGet packages into the project that utilizes those templates. Additionally, the issue centers around the new PackageReference feature of NuGet. Everything works just fine if I utilize the packages.config method of NuGet insteadMystical
Just out of curiosity, is there a reason you want/need to use the PackageReference feature of NuGet?Rommel
Yes, blog.nuget.org/20170316/… -- basically it has a lot of benefits and is the future of NuGet.Mystical
While I agree it is the future of NuGet, I think it unfortunately still has a considerable amount of bugs. Updated my answer.Rommel
Even with your update, your answer is talking about something completely unrelated (item and project templates).Mystical
@m-y - did you ever find a workaround for this? I believe I've struck the exact same scenario. It seems the the VSIX packaging tool does not play nicely with the new PackageReference nuget flavor while the build system does... very frustrating!Gymnosperm
@mmacneil007: I had to revert back to using the packages.config way of doing NuGet instead.Mystical
C
-2

The option that works for Visual Studio 2017 is NuGet packages referenced via PackageReference don't include DLLs in VSIX. However, use the version suggested by the author:

<Target Name="IncludePackageReferenceDependencies" AfterTargets="GetVsixSourceItems">
  <ItemGroup>
    <VSIXSourceItem Include="@(ReferencePath)" Condition="$([System.String]::new('%(ReferencePath.FusionName)').StartsWith('NuGet.VisualStudio'))" />
  </ItemGroup>
</Target>

Don't try the version suggested by Simon Mourier. That may have worked in VS 2015, but it doesn't work now. Also note that this solution is for the PackageReference version of NuGet. It may work for the packages.config, but I didn't have the patience to test it out.

Crusty answered 4/6, 2018 at 11:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.