I am trying to make a project template for internal use that has all of the custom parts of our assembly versioning system.
The default project template works perfectly with our pre-build and post-build event but when I try to reference a file using the $(SolutionDir) macro it gets replaced during the building of the template and
<ItemGroup>
<Compile Include="$(SolutionDir)\CommonAssemblyInfo.cs">
<Link>Properties\CommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
Gets turned into the following when the project template is used to generate a project in solution:
<ItemGroup>
<Compile Include="..\..\..\..\..\Users\<username>\AppData\Local\Temp\n0u03z2x.gpe\CommonAssemblyInfo.cs">
<Link>Properties\CommonAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
The template build/package process is probably replacing this.
How do I escape it ?
Visual studio project template replaces “$(SolutionDir)” macro in template on build
You should set CreateInPlace in the .vstemplate file of the exported project template to true, like <CreateInPlace>true</CreateInPlace>.
Following is my .vstemplate file:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
<TemplateData>
<Name>TestDemo</Name>
<Description><No description available></Description>
<ProjectType>CSharp</ProjectType>
<ProjectSubType>
</ProjectSubType>
<SortOrder>1000</SortOrder>
<CreateNewFolder>true</CreateNewFolder>
<DefaultName>TestDemo</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
<LocationField>Enabled</LocationField>
<EnableLocationBrowseButton>true</EnableLocationBrowseButton>
<Icon>__TemplateIcon.ico</Icon>
<CreateInPlace>true</CreateInPlace>
</TemplateData>
<TemplateContent>
<Project TargetFileName="TestDemo.csproj" File="TestDemo.csproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" TargetFileName="Class1.cs">Class1.cs</ProjectItem>
<Folder Name="Properties" TargetFolderName="Properties">
<ProjectItem ReplaceParameters="true" TargetFileName="AssemblyInfo.cs">AssemblyInfo.cs</ProjectItem>
</Folder>
</Project>
</TemplateContent>
</VSTemplate>
Detailed steps:
Export the project template without Automatically import the template into Visual Studio:
Unzip the exported file, add <CreateInPlace>true</CreateInPlace> into the MyTemplate.vstemplate file, and zip all the files.
Copy this file to the folder: C:\Users\<Username>\Documents\Visual Studio 2017\Templates\ProjectTemplates
Restart your Visual Studio, create a new project with the new custom template.
With this setting, this issue should be fix. But the weird thing is that the documentation states that the default value for CreateInPlace is true.
Hope this helps.
Related
I've been trying to make my own template in VS for C++.
I want to have a cpp and hpp file with the same name as the project.
I have already read this link: How can I set a file name using a variable in a Visual Studio project template
Howerer, when using my template, the files are not in the project that I've created.
Here is my vstemplate file:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
<TemplateData>
<Name>My Template</Name>
<Description>A test template</Description>
<ProjectType>VC</ProjectType>
<ProjectSubType>
</ProjectSubType>
<SortOrder>1000</SortOrder>
<CreateNewFolder>true</CreateNewFolder>
<DefaultName>MyProject</DefaultName>
<ProvideDefaultName>true</ProvideDefaultName>
<LocationField>Enabled</LocationField>
<EnableLocationBrowseButton>true</EnableLocationBrowseButton>
<Icon>__TemplateIcon.png</Icon>
<PreviewImage>__PreviewImage.png</PreviewImage>
</TemplateData>
<TemplateContent>
<Project TargetFileName="MyTemplate.vcxproj" File="MyTemplate.vcxproj" ReplaceParameters="true">
<ProjectItem ReplaceParameters="true" TargetFileName="$safeprojectname$.vcxproj.filters">MyTemplate.vcxproj.filters</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="$safeprojectname$.cpp">MyFile.cpp</ProjectItem>
<ProjectItem ReplaceParameters="true" TargetFileName="$safeprojectname$.hpp">MyFile.hpp</ProjectItem>
</TemplateContent>
</VSTemplate>
What am I doing wrong?
Edit: Managed to figure it out, had to replace file names in vcxproj file itself. Thanks for helping!
I ended up succeeding using the following method:
I added two files to my template, named $safeprojectname$.hpp and $safeprojectname$.cpp.
I edited my vcxproj file (using notepad++, or any other text editor for that matter), adding the following tags inside of the main Project tag:
<ItemGroup>
<ClInclude Include="%24safeprojectname%24.hpp" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="%24safeprojectname%24.cpp" />
</ItemGroup>
I had to use %24 as $ is not a valid character in this context, and 24 is the ASCII (/unicode) value of that character.
I'm using visual studio templates in order to build a custom visual studio template project. I'm trying to create a folder with a name «External Models» that has space char but the visual studio is creating a folder with the name «External%20Models» replacing the space by %20.
Follows my .vstemplate file:
<VSTemplate Version="3.0.0" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005" Type="Project">
<TemplateData>
...
</TemplateData>
<TemplateContent>
<Project TargetFileName="Product.Models.csproj" File="Product.Models.csproj" ReplaceParameters="true">
...
<Folder Name="GeneratedCode" TargetFolderName="GeneratedCode">
...
</Folder>
<Folder Name="External Models" TargetFolderName="External Models">
<Folder Name="CorePatterns" TargetFolderName="CorePatterns">
...
</Folder>
</Folder>
</Project>
</TemplateContent>
<WizardExtension>
...
</WizardExtension>
And the content of the .vsix files generated:
I changed from this:
<Folder Name="External Models" TargetFolderName="External Models">
<Folder Name="CorePatterns" TargetFolderName="CorePatterns">
...
</Folder>
</Folder>
To this, and start to work.
<Folder Name="ExternalModels" TargetFolderName="External Models">
<Folder Name="CorePatterns" TargetFolderName="CorePatterns">
...
</Folder>
</Folder>
Explanation:
It does not matter which folders are generated to create the .vsix installer. What is matter is TargetFolderName="External Models" tag name which will generate the project folder (during the Visual Studio->File->Create new project). By changing the Name="External Models" to Name="ExternalModels" and, in the template project that generate the .vsix, change the name of the folder "External Models" to "ExternalModels" everithing will work fine.
Visual Studio 2013. I create own template.
its vstemplate-file has such records:
<Folder Name="batch-build" TargetFolderName="batch-build">
<ProjectItem ReplaceParameters="true" TargetFileName="1_debug-build-all-versions.bat">
<ProjectItem ReplaceParameters="true" TargetFileName="2_debug-build-all-versions-with-Gallio-tests.bat">
<ProjectItem ReplaceParameters="true" TargetFileName="3_debug-build-all-versions-with-NUnit-tests.bat">
<ProjectItem ReplaceParameters="true" TargetFileName="4_release-build-all-versions.bat">
</Folder>
I need all this files would be copied into my new project, based on this template.
But the csproj-file of this template has some conditions:
<ItemGroup>
<None Include="batch-build\1_debug-build-all-versions.bat" />
<None Include="batch-build\4_release-build-all-versions.bat" />
</ItemGroup>
<Choose>
<When Condition="'$(Build_With_Tests_Of)' == 'NUnit'">
<ItemGroup>
<None Include="batch-build\3_debug-build-all-versions-with-NUnit-tests.bat" />
</ItemGroup>
</When>
<When Condition="'$(Build_With_Tests_Of)' == 'Gallio'">
<ItemGroup>
<None Include="batch-build\2_debug-build-all-versions-with-Gallio-tests.bat" />
</ItemGroup>
</When>
</Choose>
When new project created, by default the Build_With_Tests_Of property has the Gallio value. Therefore in Solution Explorer shows the batch-build\2_debug-build-all-versions-with-Gallio-tests.bat file. This is what I need. But if I will open the directory of my new project, than I see - the batch-build\3_debug-build-all-versions-with-NUnit-tests.bat file was not copyed. So, template don't copy files, which is not displayed in the Solution Explorer. But I need their copies complettely.
How to force a template to copy all files?
I had the same issue. Here's my solution:
Add the needed file to the solution. At it's properties tab, mark it as a resource. Now, create you template.
Changing a file to resource will make the template copy that file (assuming you didn't include it at the solution in the first place because it should not be complied)
Hope this helps, this is the solution I used to include a AssemblyInfo_Template.cs file in a template project. (AssemblyInfo_Template.cs is used by SubWCRev.exe to overwrite AssemblyInfo.cs in order to include the revision number in AssemblyInfo.cs)
I'm trying to create a custom item template for Visual Studio that creates multiple files. Two of those files are Resource.resx file and a corresponding 'Resource.Designer.cs' file.
I've managed to display them as a parent-child files with this declaration in the .vstemplate file:
<ProjectItem ItemType="EmbeddedResource" TargetFileName="$fileinputname$Resources.resx" ReplaceParameters="true">Resources.resx</ProjectItem>
<ProjectItem TargetFileName="$fileinputname$Resources.resx\$fileinputname$Resources.Designer.cs" ReplaceParameters="true">Resources.Designer.cs</ProjectItem>
This also declared Resource.resx as an embedded resource.
The problem I'm getting now is that the Resource.resx file doesn't use Resources.Designer.cs as a code behind file after creating item with this template. As soon as I add a new resource string in Resource.resx file, it creates a new Resources1.Designer.cs file which Visual Studio uses as a code behind from that point.
I've examined the changes made in .csproj file before and after Visual Studio creates a new code-behind file and I found that the main reason is because there were no <LastGenOutput> entries for Resource.resx file.
Is there some way to declare <LastGenOutput> through .vstemplate or any other way to connect .resx file with it's code-behind file without doing it manually?
It isn't very clear why you need this template since it is already included with Visual Studio. You select it with Project + Add New Item + General + Resources File.
If you want to customize it then your best bet is to get started with the existing one. Navigate to C:\Program Files (x86)\Microsoft Visual Studio x.x\Common7\IDE\ItemTemplatesCache\CSharp\General\1033\Resource.zip where x.x is the VS version number and 1033 might be different if you don't use the English version of VS.
I'll just post the .vstemplate file you'll find there, be sure to copy/paste the file to get started on your own:
<?xml version="1.0" encoding="utf-8"?>
<VSTemplate Version="3.0.0" Type="Item" xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name Package="{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}" ID="2390" />
<Description Package="{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}" ID="2391" />
<Icon Package="{FAE04EC1-301F-11d3-BF4B-00C04F79EFBC}" ID="4565" />
<TemplateID>Microsoft.CSharp.Resource</TemplateID>
<ProjectType>CSharp</ProjectType>
<RequiredFrameworkVersion>2.0</RequiredFrameworkVersion>
<NumberOfParentCategoriesToRollUp>1</NumberOfParentCategoriesToRollUp>
<DefaultName>Resource.resx</DefaultName>
</TemplateData>
<TemplateContent>
<ProjectItem>Resource.resx</ProjectItem>
<CustomParameters>
<CustomParameter Name="$itemproperties$" Value="CustomTool" />
<CustomParameter Name="$CustomTool$" Value="ResXFileCodeGenerator" />
</CustomParameters>
</TemplateContent>
<WizardExtension>
<Assembly>Microsoft.VisualStudio.Editors, Version=9.0.0.0, Culture=Neutral, PublicKeyToken=b03f5f7f11d50a3a</Assembly>
<FullClassName>Microsoft.VisualStudio.Editors.ResourceEditor.ResxItemWizard</FullClassName>
</WizardExtension>
</VSTemplate>
If you want to add more files then add more <ProjectItem> elements.
The parent-child relation should be declared using the DependendUpon tag in the C# project file (.csproj), like this:
<Project ...>
...
<ItemGroup>
...
<EmbeddedResource Include="Resources.resx">
...
</EmbeddedResource>
<Compile Include="Resources.Designer.cs">
<DependentUpon>Resources.resx</DependentUpon>
...
</Compile>
...
</ItemGroup>
</Project>
I've followed this tutorial to try to add a template to Visual Studio:
http://www.switchonthecode.com/tutorials/visual-studio-how-to-create-item-templates
The template I have created is designed to add one predefined .aspx and one predefined .aspx.cs file to the project.
The folder contains the following files:
MoosePage.aspx
MoosePage.aspx.cs
MoosePage.vstemplate
MoosePageItemTemplateIcon.ico
The .vstemplate file looks like this:
<VSTemplate Type="Item" Version="2.0.0"
xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>MoosePage</Name>
<Description>MoosePage Template</Description>
<DefaultName>NewMoosePage</DefaultName>
<ProjectType>CSharp</ProjectType>
<Icon>MoosePageItemTemplateIcon.ico</Icon>
</TemplateData>
<TemplateContent>
<ProjectItem TargetFileName="$fileinputname$.aspx" ReplaceParameters="true">
MoosePage.aspx
</ProjectItem>
<ProjectItem TargetFileName="$fileinputname$.aspx.cs" ReplaceParameters="true">
MoosePage.aspx.cs
</ProjectItem>
</TemplateContent>
</VSTemplate>
I have zipped the files up (.zip not .zipx) and placed the zip folder in My Documents\Visual Studio 2008\Templates\ItemTemplates\VisualWebDeveloper.
I have restarted Visual Studio.
When I go into my website project and choose Add New Item, I don't see my new template.
Can anyone suggest what might have gone wrong?
Thanks
David
I have found out there is a wizard to create templates in File -> Export Template.
Using this wizard, I found out that my .vstemplate file had the wrong ProjectType. I changed it to this...
<VSTemplate Type="Item" Version="2.0.0"
xmlns="http://schemas.microsoft.com/developer/vstemplate/2005">
<TemplateData>
<Name>MoosePage.aspx</Name>
<Description>MoosePage Template</Description>
<DefaultName>NewMoosePage</DefaultName>
<ProjectType>Web</ProjectType>
<ProjectSubType>CSharp</ProjectSubType>
<Icon>MoosePageItemTemplateIcon.ico</Icon>
</TemplateData>
<TemplateContent>
<ProjectItem TargetFileName="$fileinputname$.aspx" ReplaceParameters="true">
MoosePage.aspx
</ProjectItem>
<ProjectItem TargetFileName="$fileinputname$.aspx.cs" ReplaceParameters="true">
MoosePage.aspx.cs
</ProjectItem>
</TemplateContent>
</VSTemplate>
And now it works fine.
I can also confirm that the new .zipx format is NOT supported.
Now to wait two years before I can mark my own answer as correct.
Cheers
David