VSIX with Project Templates and NuGet Packages
Asked Answered
M

3

5

I have been following this post about how to build a VSIX project that will add some custom MVC project types:

http://www.asp.net/mvc/tutorials/mvc-4/custom-mvc-templates

I also want to include some additional Nuget packages, so I was following this page from Nuget, but it seems to be for VS2010 and I'm working in 2012.

I have the project building, and everything works peachy on my machine. The install works, the new project type appears, and when I create a new project of this type, everything works perfectly.

However, when I send the installer to a coworker, things break. The installer works, they see the new project type, but when creating the project he gets error messages about not being able to install any of the packages in the extension node. I've confirmed the Product Id of the extension is correct (I intentionally malformed it in the .vstemplate file during testing and it gave an entirely different error). I've added the packages to the extension manifest, but it doesn't seem to make a difference. I've also confirmed the .nupkg files get deployed to %ProgramFiles(x86)%\Microsoft Visual Studio 11.0\Common7\IDE\Extensions.

Any suggestions on what to do?

Custom Project's .vstemplate section

<WizardExtension>
    <Assembly>NuGet.VisualStudio.Interop, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
    <FullClassName>NuGet.VisualStudio.TemplateWizard</FullClassName>
</WizardExtension>
<WizardData>
    <packages repository="registry" keyName="AspNetMvc4VS11" isPreunzipped="true">
        <package id="EntityFramework" version="5.0.0" skipAssemblyReferences="true" />
        <package id="jQuery" version="1.8.2" />
        <!-- snip -->
    </packages>
    <packages repository="extension" repositoryId="SampleExtensionId">
      <package id="Unity" version="3.0.1304.0" targetFramework="net45" />
      <package id="Unity.WebAPI" version="0.10" targetFramework="net45" />
      <!-- snip -->
    </packages>
</WizardData>

source.extension.vsixmanifest Asset tags

<Assets>
    <Asset d:VsixSubPath="ProjectTemplates\CustomMVCTemplate" etc/>
    <Asset Type="Unity.3.0.1304.0" Path="Packages\Unity.3.0.1304.0.nupkg" />
    <Asset Type="Unity.WebAPI.0.10" Path="Packages\Unity.WebAPI.0.10.nupkg" />
    <!-- snip -->
</Assets>

File Structure

  • Extension Project
    • Packages
      • NugetPackage 1
      • NugetPackage 2
      • etc
    • ProjectTemplates
      • CustomMVCTemplate
        • <custom project files>
    • source.extension.vsixmanifest
Mcguire answered 12/7, 2013 at 17:23 Comment(0)
R
5

I've made a step by step video on how to make a VSIX that auto downloads nuget packages.

http://www.youtube.com/watch?v=_ZvsFz41H-E

Since there are many steps and I never wrote them down, I won't type them here. I've definitely tested my VSIX package on other people's machine and it worked so hopefully this will work for you.

Ranchero answered 28/8, 2013 at 1:12 Comment(2)
For anyone who's interested in just the relevant part, it starts at 22:47Oto
unfortunately it does not download. With this way, packages are just added to project if they have been already downloaded.Wares
A
2

To download latest versions of NuGet packages plus all their dependencies add a following class to your vsix:

public class MyProjectWizard : IWizard
{
    IEnumerable<string> _packages;

    public void RunStarted(object automationObject, Dictionary<string, string> replacementsDictionary, WizardRunKind runKind, object[] customParams)
    {
        if (customParams.Length > 0) {
            var vstemplate = XDocument.Load((string)customParams[0]);
            _packages = vstemplate.Root
                .ElementsNoNamespace("WizardData")
                .ElementsNoNamespace("packages")
                .ElementsNoNamespace("package")
                .Select(e => e.Attribute("id").Value)
                .ToList();
        }
    }

    public void ProjectFinishedGenerating(Project project)
    {
        var componentModel = (IComponentModel)Package.GetGlobalService(typeof(SComponentModel));
        var _installer = componentModel.GetService<IVsPackageInstaller2>();

        foreach (var package in _packages) {
            _installer.InstallLatestPackage(null, project, package, false, false);
        }
    }
}

And then use following in vstemplate:

  <WizardExtension>
    <Assembly>MyProjectWizard, Version=1.0.0.0, Culture=neutral, PublicKeyToken=22c2a1a5fa7b6905</Assembly>
    <FullClassName>MyProjectWizard.MyProjectWizard</FullClassName>
  </WizardExtension>
Agostino answered 30/7, 2017 at 4:14 Comment(3)
Where is Package defined? From this line: (IComponentModel)Package.GetGlobalService(typeof(SComponentModel));Malave
Answer to above is: using Microsoft.VisualStudio.Shell; Assembly: Microsoft.VisualStudio.Shell.15.0.dllMalave
what are all these namespaces? Where's IWizard, where's Project? Would it kill to post entire file?Shoe
I
1

Check out this link http://samritchie.net/2012/09/17/nuget-packages-in-vs2012-templates/ which helped me. However, I'm still running into the issue where all my references' paths are empty.

Note especially the following comment from the article linked above:

I spent a considerable period of time attempting to work out what the v2 equivalent of CustomExtension was, but to cut a long story short, you don’t need to make any changes to the .vsixmanifest — it’s enough to include all of the packages in the VSIX under a ‘Packages’ directory.

Isogamy answered 27/7, 2013 at 0:12 Comment(1)
Excellent find. I added key paragraph straight into your answer too.Schulz

© 2022 - 2024 — McMap. All rights reserved.