Search code examples
visual-studiotemplatesmsbuildcsprojvisual-studio-templates

Visual studio project template replaces "$(SolutionDir)" macro in template on build


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 ?


Solution

  • 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>&lt;No description available&gt;</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:

    1. Export the project template without Automatically import the template into Visual Studio: enter image description here

    2. Unzip the exported file, add <CreateInPlace>true</CreateInPlace> into the MyTemplate.vstemplate file, and zip all the files.

    3. Copy this file to the folder: C:\Users\<Username>\Documents\Visual Studio 2017\Templates\ProjectTemplates

    4. Restart your Visual Studio, create a new project with the new custom template.

      enter image description here

    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.

    enter image description here

    Hope this helps.