VSIX with Project Templates and NuGet Packages - visual-studio-2012

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

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.

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>

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.

Related

WebJobsStartup in Azure Functions v2 not working when targeting netcoreapp2.1

I have an Azure Function v2 app, that I originally targeted netcoreapp2.1.
I then have a Startup.cs class, annotated with [assembly: WebJobsStartup(typeof(Startup))] to set up dependency injection, but it did not register Startup in the extensions.json file.
This is happening during build. Publish has another issue at the moment.
When I change the TargetFramework in the project file to netstandard2.0 it successfully adds Startup to extensions.json:
{
"extensions":[
{ "name": "AzureStorage", "typeName":"Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"},
{ "name": "Startup", "typeName":"MyApp.Functions.Startup, MyApp.Functions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}
]
}
While I do not have exact reasons to target netcoreapp2.1, I am curious to figure out why it doesn't work, as v2 was changed to target .Net Core by default.
I have upgraded the Microsoft.NET.SDK.Functions to version 1.0.26 from manage nuget packages and it worked.
This looks fixed now just upgrade Microsoft.NET.SDK.Functions to version 1.0.25 +
In my case, I had simply missed to explicitly set host.json to be copied. Adding these rows to the csproj file did the works:
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

invalid classes root with buck project on android studio

I'm trying to add several libraries, such as fresco to a buck project. Here is the code that adds fresco:
maven/BUCK
### Package com.facebook.fresco:fresco
remote_file(
name = 'com_facebook_fresco__fresco-remote',
out = 'com_facebook_fresco__fresco-remote.aar',
sha1 = '86df1ab4b0074e1aeceb419593d2ea6d97cdc3b4',
url = 'http://repo1.maven.org/maven2/com/facebook/fresco/fresco/0.11.0/fresco-0.11.0.aar'
)
android_prebuilt_aar(
name = 'com_facebook_fresco__fresco',
aar = ':com_facebook_fresco__fresco-remote',
deps = [
'//maven:com_facebook_fresco__imagepipeline',
'//maven:com_facebook_fresco__drawee',
'//maven:com_facebook_fresco__imagepipeline-base',
'//maven:com_parse_bolts__bolts-tasks',
'//maven:com_android_support__support-v4',
'//maven:com_nineoldandroids__library',
'//maven:com_facebook_fresco__fbcore',
],
visibility = ['PUBLIC']
)
Here is for example a file generated by buck project --ide INTELLIJ:
.idea/libraries/library_maven_com_facebook_fresco__fresco.xml
<component name="libraryTable">
<library name="library_maven_com_facebook_fresco__fresco">
<CLASSES>
<root url="jar://$PROJECT_DIR$/buck-out/gen/maven/com_facebook_fresco__fresco-remote/com_facebook_fresco__fresco-remote.aar!/" />
</CLASSES>
<JAVADOC />
<SOURCES />
</library>
</component>
The aar file exists in said dir.
But I get invalid classes root
Full project https://github.com/vinz243/snappy
I'm pretty sure this is a bug in Buck with the new Android project generation. You can get the old one by passing --deprecated-ij-generation when you invoke buck project.
You should probably file an issue for this, however :)

Adding additional content folders to Azure package

Im using Azure SDK 2.5
I have a web role in a cloud service project. I would like to add a folder in some fashion such that it is deployed in the parent directory of the approot. I havent found a way to do this which kind of makes me wonder what use is the ability to define virtual directories in csdef.
So I thought I would try adding folders via the Contents/Content xml config in the csdef. I am either fundamentally misunderstanding what this bit of config does or its hopelessly broken.
Assuming this folder structure
/
/CloudService
/SomeOtherContent
If I define the following:
<Contents>
<Content destination="frontend">
<SourceDirectory path="..\SomeOtherContent" />
</Content>
</Contents>
and build I get:
error CloudServices089: Cannot find the source directory
'C:\src\template\src\Template.CloudService\bin\Debug\..\SomeOtherContent'
Ok so its starting the bin\Debug, so I'll just make it ..\..\..\SomeOtherContent
error CloudServices089: Cannot find the source directory
'C:\src\template\src\Template.CloudService\..\..\..\SomeOtherContent'
Yes thats right, the folder at which my relative path is resolved has changed!!! Its no longer bin\Debug. Wtf!? How can this be made to work? It works if i enter a full drive qualified absolute path.
So I solved this by having MSBuild resolve the path and push it in to an environment variable which I called FrontendDir.
<Contents>
<Content destination="frontend">
<SourceDirectory path="%FrontendDir%" />
</Content>
</Contents>
and in the ccproj I added:
<UsingTask
TaskName="SetEnvironmentVariableTask"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll">
<ParameterGroup>
<Name ParameterType="System.String" Required="true" />
<Value ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Environment.SetEnvironmentVariable(Name, Value);
]]>
</Code>
</Task>
</UsingTask>
<Target Name="BeforeBuild" Condition=" '$(FrontendDir)' == '' ">
<Message Text="Setting Project Dir" Importance="high" />
<SetEnvironmentVariableTask Name="FrontendDir" Value="$(ProjectDir)\..\Template.FrontEnd\dist" />
</Target>
Its preferable to put the entire path into the env var here as you can then override it easily in your different build scenarios by overriding the value (eg. /p:FrontendDir="c:\foo")
So that works and works fairly well. I still say the behaviour I was seeing before with the relative path resolution changing folders is... broken. It just doesn't work with relative paths in any usable way.
You are seeing the same error but from different msbuild targets.
The first error (when using ..\..\) is thrown at PreValidateServiceModel which passes in the Source location and checks the path
ServiceDefinitionFile="#(SourceServiceDefinition)"
ServiceConfigurationFile="#(SourceServiceConfiguration)"
C:\src\Azure\ServiceDefinition.csdef : error CloudServices089: Cannot
find the source directory 'C:\src\Azure\..\..\Installers\' in role
WebHost. [C:\src\Azure\Azure.ccproj]
Done building target "PreValidateServiceModel" in project "Azure.ccproj" -- FAILED.
The second error is thrown at ValidateServiceFiles which passes in the Target location
ServiceDefinitionFile="#(TargetServiceDefinition)"
ServiceConfigurationFile="#(TargetServiceConfiguration)">
C:\src\Azure\bin\Release\ServiceDefinition.csdef : error CloudServices089: Cannot
find the source directory
'C:\src\Azure\bin\Release\Installers\'
in role WebHost. [C:\src\Azure\Azure.ccproj]
Done building target "ValidateServiceFiles" in project "Azure.ccproj" -- FAILED.
If you reflect on C:\Program Files\Microsoft SDKs\Azure.NET SDK\v2.9\bin\ServiceDescription.dll you can see the ProcessRoleContents method doing the validation but using the SourceFile to resolve the location.
One option is to make sure the target folder exists (even if empty) before the build starts.
It would be better if the PreValidation resolved the path and when the Target is saved, it had the full path.
I ended up editing the ccproj, and adding this
<Target Name="BeforeAddRoleContent">
<ItemGroup>
<AzureRoleContent Include="Installers\">
<RoleName>Azure</RoleName>
<Destination></Destination>
</AzureRoleContent>
</ItemGroup>
</Target>
Referencing runtime content from .ccproj (Azure SDK 2.9)

OwinHost.exe not working for class library project

I've created a new class library project with the following startup class:
public class Startup
{
public void Configure(IAppBuilder app)
{
app.Run(ctx =>
{
ctx.Response.StatusCode = 200;
ctx.Response.ContentType = "text/plain";
return ctx.Response.WriteAsync("Hello from Owin");
});
}
}
I have the following packages installed:
<packages>
<package id="Microsoft.Owin" version="2.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.HttpListener" version="2.1.0" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="OwinHost" version="2.1.0" targetFramework="net45" />
</packages>
When I attempt to run owinhost.exe from /bin/debug I get the following error:
Error: System.EntryPointNotFoundException
The following errors occurred while attempting to load the app.
- No assembly found containing an OwinStartupAttribute.
- No assembly found containing a Startup or [AssemblyName].Startup class.
Do I need to do anything else to get OwinHost.exe to work with a class library project (I had the same issue with a Console application).
If you execute the OwinHost.exe without parameters, the method name needs to be Configuration, not Configure.
Also, execute owinhost.exe under the root path (A.K.A {projectDir}) and output the builds to /bin, not /bin/debug. Of course, these are configurable through switches to OwinHost.exe but this is what it needs if you wanna run it w/o any switches.
More in depth explanation is available here: OWIN Startup Class Detection and here: Good Old F5 Experience With OwinHost.exe on Visual Studio 2013

MSI installed VSPackage is loaded in Experimental Instance only

My package is only loaded in Experimental Instance.
I have the following package class attributes:
[PackageRegistration(UseManagedResourcesOnly = true)]
[InstalledProductRegistration("#110", "#112", "3.6.1365", IconResourceID = 400)]
[ProvideMenuResource("Menus.ctmenu", 1)]
[Guid(GuidList.guidVSPackage2012PkgString)]
public sealed class VSixPackage : Package
pkgdef file content:
[$RootKey$\InstalledProducts\VSixPackage]
#="#110"
"Package"="{011cc127-af13-4974-903a-9e6518b2b641}"
"PID"="3.6.1365"
"ProductDetails"="#112"
"LogoID"="#400"
[$RootKey$\Packages\{011cc127-af13-4974-903a-9e6518b2b641}]
#="VSixPackage"
"InprocServer32"="$WinDir$\SYSTEM32\MSCOREE.DLL"
"Class"="Vsix3_6_1365.VSixPackage"
"CodeBase"="$PackageFolder$\Vsix3_6_1365.dll"
[$RootKey$\Menus]
"{011cc127-af13-4974-903a-9e6518b2b641}"=", Menus.ctmenu, 1"
extension.vsixmanifest :
<PackageManifest Version="2.0.0" xmlns="http://schemas.microsoft.com/developer/vsx-schema/2011">
<Metadata>
<Identity Id="011cc127-af13-4974-903a-9e6518b2b641" Version="3.6.1365" Language="en-US" Publisher="Ltd." />
<DisplayName>Package 3.6.1365</DisplayName>
<Description>etc...</Description>
<Icon>Resources\Package.ico</Icon>
</Metadata>
<Installation InstalledByMsi="true" AllUsers="true">
<InstallationTarget Id="Microsoft.VisualStudio.Pro" Version="[11.0,12.0)" />
<InstallationTarget Version="[11.0,12.0)" Id="Microsoft.VisualStudio.Premium" />
<InstallationTarget Version="[11.0,12.0)" Id="Microsoft.VisualStudio.Ultimate" />
</Installation>
<Dependencies>
<Dependency Id="Microsoft.Framework.NDP" DisplayName="Microsoft .NET Framework" Version="4.5" />
<Dependency Id="Microsoft.VisualStudio.MPF.11.0" DisplayName="Visual Studio MPF 11.0" Version="11.0" />
</Dependencies>
<Assets>
<Asset Type="Microsoft.VisualStudio.VsPackage" Path="Vsix3_6_1365.pkgdef" />
</Assets>
</PackageManifest>
These files (including Vsix3_6_1365.dll) are installed to
"%VSInstallDir%\Common7\Ide\Extensions\Your Company\Your Product\Version"
folder.
When .vsix file is created it registers the Package successfully but I need to do this automatically with msi.
How can it be registered for original Visual Studio (not Experimental Instance)?
Update1:
I have several packages (different versions) with
[$RootKey$\InstalledProducts\VSixPackage]
in .pkgdef file. Can it be the reason of the problem?
Update2:
I tried different names instead of "VSixPackage" (added version like VSixPackage3_6_1382) but this did not help.
Strange thing these VSPackages - they were working for a while - I used VSExtension:VsixPackage to install my package - it ceased to delete it during uninstall. And it could not register the Package for VS2013. Now this problem.
The provided attributes on the package class, package definition file and extension manifest seem to be okay. I guess the reason why the extension is only loaded by the experimental hive is because Visual Studio registers the extension when you build it (at least before you run the extension through the debugger when pressing F5).
When you install your extension via MSI you must register the extension programmatically... just copying the extension assembly files to the extensions folder within Visual Studio´s installation directory does not work. If you´re using the WiX toolset to assemble the Windows installer package, you can use the VsixPackage element to register the extension.
You´ll find the documentation at: http://wixtoolset.org/documentation/manual/v3/xsd/vs/vsixpackage.html
If your extension does not require any special installation tasks (like writing to the registry or setting up other tools and/or third-party components), an MSI installation is not needed, instead you can install the extension by just executing the vsix file from Windows Explorer; this will show a dialog where you´ve to confirm the installation.
I never tried to setup an extension manually, but you could try to set the following keys (maybe some more might be required; just examine the configuration of the experimental hive to figure all required keys and values)...
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0_Config\InstalledProducts\<package-name>
REGSZ: (Default) = #110
REGSZ: LogoId = #400
REGSZ: Package = <package-guid>
REGSZ: PID = <package-product-id>
REGSZ: ProductDetails = #112
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0_Config\BindingPaths\<package-guid>
REGSZ: <package-installation-folder-path> = ""
HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\11.0_Config\Packages\<package-guid>
REGSZ: (Default) = <package-name>
REGSZ: Class = <package-class-fullname>
REGSZ: CodeBase = <package-assembly-fullpath>
REGSZ: InprocServer32 = "C:\Windows\SYSTEM32\MSCOREE.DLL"

Resources