T4 templates not generating output in new VS2017 csproj projects - t4

I migrated a project.json/.xproj project to the newer CS2017 .csproj format.
The project contains a T4 (.tt) template file.
It doesn't regenerate its output on save or build. The output .cs file isn't nested below the .tt file either.
Is there something I have to do to get this working?

.tt files are only auto-run by VS on save. You can install AutoT4 to have them run before/after build. (Be aware that at the moment there is a limitation with the new .csproj files - the options don't show up for them in the properties window.)
If you've converted from the old project.json/.xproj format, you may need to add the template to the project explicitly:
<ItemGroup>
<None Update="Foo.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>Foo.cs</LastGenOutput>
</None>
<Compile Update="Foo.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Foo.tt</DependentUpon>
</Compile>
</ItemGroup>
Related GitHub issue
Edit
As mentioned in the comments below, you can do this quickly & easily by excluding, then including the template in your project.

I realise this is 2+ years old but for those bumping into this issue years on like me, the method listed below works for me without installing anything. I had the exact same issue, after upgrading a project from Visual Studio 2010 to Visual Studio 2017. YMMV. Make a backup copy of your .csproj file before you start.
Forcing rebuild of all .tt files when you build your project can be achieved without installing anything, by editing the .csproj project file. Editing the .csproj file seems clunky, but is is the approved way https://learn.microsoft.com/en-gb/visualstudio/modeling/code-generation-in-a-build-process?view=vs-2015
Within your .csproj file, you will find lots of PropertyGroup nodes. At the end of the list of PropertyGroup nodes (position not critical), add another PropertyGroup node with this content:
<PropertyGroup>
<TransformOnBuild>true</TransformOnBuild>
<TransformOutOfDateOnly>false</TransformOutOfDateOnly>
</PropertyGroup>
Now look near the end of the .proj file, and you will see a line like this:
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
(For interest, on my computer with VS2017 on it that resolves to C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin\Microsoft.CSharp.targets)
Beneath that line, add a line like this:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v15.0\TextTemplating\Microsoft.TextTemplating.targets" />
(For interest, on my computer that resolves to C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\Microsoft\VisualStudio\v15.0\TextTemplating\Microsoft.TextTemplating.targets)
YMMV. If yours is a web project, there is probably a line nearby that is similar but to do with Microsoft.WebApplication.targets, from which you can draw inspiration.
That, possibly with a restart of Visual Studio, should do it. If you delete the transformed file that your .tt file emits, and then do a rebuild of your project, you should see that the emitted file reappears.

Related

Visual Studio - Prevent Creation of <Compile> and <None> tags when moving files in CSPROJ

In my CSPROJ I have a subfolder ›None‹. It is setup like this:
<ItemGroup Label="None">
<Compile Remove="None/**/*.cs" />
<None Include="None/**/*.cs" />
</ItemGroup>
In there I have CS files, that I don't want to compile.
No, I want to move a file (lets say ‌›CompileIt.cs‹ from ›None‹ back to the project, because now I want to compile it again.
If I move it outside of Visual Studio (like directly in the explorer or via PowerShell) it does exactly what I want, the file is now in a different folder inside the project and the Build-Action changes from ›None‹ to ›C# Compiler‹.
But if I move the file in Visual Studio, something different happens. Visual Studio changes the CSPROJ file like this:
<ItemGroup Label="None">
<Compile Remove="None/**/*.cs" />
<None Include="None/**/*.cs" />
</ItemGroup>
<ItemGroup>
<None Include="CompileIt.cs" />
</ItemGroup>
Now I have to either delete the ItemGroup from the CSPROJ again or change the "Build Action" in the Solution Explorer`s Properties page of the file.
Of course I know, this is usually exactly what you would expect, because normally a build action shouldn't change if you only move the file.
But anyway, is there a way to let Visual Studio know to not change CPSROJ file if I move a file inside it?
Or alternatively, is there a way to mark a subfolder in Visual Studio so that Visual Studios knows it should ignore all files in it?
PS: Oh, I forgot to say this, it is a Core-Style CSPROJ file, that means, all CS files are included automatically.

Using rider and visual studio for the same project?

I work on a dotnet project in rider. My colleague works on the same project and prefers visual studio. The project contains a lot of test fixtures (thousands). Rider tries to index all those files, which I don't need. So I exclude the test file folder from the index. What rider does is it adds one line per file in the excluded folder to the .csproj file:
<ItemGroup>
<Folder Include="excludedDir\subdir1\" />
<Folder Include="excludedDir\subdir2\" />
<_ContentIncludedByDefault Remove="excludedDir\file_0001.xml" />
...
<_ContentIncludedByDefault Remove="excludedDir\file_9999.xml" />
</ItemGroup>
That seems to solve the indexing problem for rider. But Visual Studio cannot handle a .csproj file that is 10'000 lines long. Just opening the project takes 5 minutes at best. So working on that project with that .csproj file is not an option anymore.
Has anyone ever had a similiar issue and found a solution to:
making VS ignore the _ContentIncludedByDefault keys
or excluding files from rider index without having rider specify each file individually?

How can I get VS to consider my project dirty when (only) an .exe Content item is dirty?

My C++ project includes a set of (non-code) files that need to be copied to the output directory verbatim. I added them to my .vcxproj as Content nodes with CopyToOutputDirectory set to PreserveNewest. For example:
<ItemGroup>
<Content Include="util.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="lib_util_needs.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<!-- etc. -->
</ItemGroup>
This almost works; when I build the project, each content file is correctly copied to the output directory if its timestamp is newer than whatever's already there. But... if I update one of these content files without modifying an actual compiled code file at the same time, Visual Studio 2017 concludes that the project is already up to date, does not build, and does not copy the newer version of the content file to the output directory. Is there anything I can do about this? Things that do not work:
Setting PublishState to Prerequisite under the Content node
Listing content files as DependentUpon nodes under a code file's node
Edit: After further investigation, it appears that the behavior depends on the content file's extension. For example, dlls behave the way I want (project marked as dirty and built if the timestamp is updated), but exes do not.
How can I get VS to consider my project dirty when (only) a Content item is dirty?
You can set the property the UpToDateCheckInput to the item:
<ItemGroup>
<UpToDateCheckInput Include="util.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</UpToDateCheckInput>
<!-- etc. -->
</ItemGroup>
Or set the property DisableFastUpToDateCheck to true in the project file to disable FastUpToDateCheck for Visual Studio build manager:
<PropertyGroup>
<DisableFastUpToDateCheck>True</DisableFastUpToDateCheck>
</PropertyGroup>
Check MSDN about DisableFastUpToDateCheck:
A boolean value that applies to Visual Studio only. The Visual Studio
build manager uses a process called FastUpToDateCheck to determine
whether a project must be rebuilt to be up to date. This process is
faster than using MSBuild to determine this. Setting the
DisableFastUpToDateCheck property to true lets you bypass the Visual
Studio build manager and force it to use MSBuild to determine whether
the project is up to date
Hope this helps.

Preventing Visual Studio from rewriting project references

I have a large solution in which the "root" project includes feature projects by glob:
<ProjectReference Include="..\Feature\*\*.csproj" />
This works, despite not looking great in the references list, but the issue that occasionally Visual Studio will rewrite the csproj with all of the project references resolved:
<ProjectReference Include="..\Feature\A\A.csproj" />
<ProjectReference Include="..\Feature\B\B.csproj" />
It's not clear what triggers this, but I'm guessing it might have something to do with NuGet.
Is there anyway to stop VS from doing this (akin to using DisableFastUpToDateCheck for custom MSBuild scenarios)?
It's not clear what triggers this, but I'm guessing it might have something to do with NuGet.
It should be related to the items in the ItemGroup. I have the similar issue before, but the difference is that I use wildcards to contain .cs files and your are .csproj files, looks like:
<ItemGroup>
<Compile Include="**\*.cs" />
</ItemGroup>
When I delete one of .cs file in the <ItemGroup>, the wildcard gets expanded in the csproj file. For you case, if I deleted the the C.csproj project from Visual Studio (Add it before, reload the root project), then I got the same result as you.
For this issue, many other community members submit a user voice to Visual Studio team: VS IDE should support file patterns in project files. Now this is well supported in the new project system used by .NET Core and .NET Standard in Visual Studio 2017, but they haven't done the work to support it for existing project types.
Is there anyway to stop VS from doing this (akin to using DisableFastUpToDateCheck for custom MSBuild scenarios)?
To resolve this issue, you can use option Exclude="..." to exclude the project that you do not want to refer to:
<ItemGroup>
<ProjectReference Include="..\Feature\*\*.csproj" Exclude="..\Feature\C\C.csproj" />
</ItemGroup>
Or, if you want to delete one of project and keep the wildcard pattern, you only need to unload the root project, then delete the reference project, reload the root project, the wildcard pattern would be preserved.
Hope this helps.
I've done further research on this.
For testing, you can consistency reproduce the expansion by renaming any project that's included in the wildcard pattern.
Also, the easiest way to prevent the expansion is to:
Move the project reference globs into Directory.Build.props or another external file
Set DisableFastUpToDateCheck to true in your csproj
Using properties doesn't work and isn't required, likewise with using an Exclude.

Stop visual studio from trying to "Add support for typescript" on each file adding

I have a solution with multiple web projects. And there is common tsconfig which is used to build all typescript in solution. Build is called via webpack, so I don't want any typescript support from visual studio. More precisely, I want some support — in navigating and refactoring, but I don't want VS to build this code.
So I removed all references to typescript targets from csproj and everything works fine. But any time I add a new typescript file, VS gladly says
Your project has been configured to support TypeScript
and returns all typescript targets back to csproj.
Can I prevent VS from doing it? Of course I can live with it, but removing garbage from csproj after each adding seems uncomfortable.
UPD: found post on uservoice of VS https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/13420095-ask-to-configure-projects-for-typescript. But maybe there is solution already available. Or you can like this uservoice if you agree that it is an annoying problem :)
Found solution on uservoice (https://visualstudio.uservoice.com/forums/121579-visual-studio-ide/suggestions/13420095-ask-to-configure-projects-for-typescript).
Seems a bit ugly but it works.
Steps to fix:
Add some ts file to project and let VS add some bullshit to your csproj
ctrl-shift-s to make sure csproj is updated
Open csproj in any text editor and then:
Find import of Microsoft.TypeScript.Default.props and replace it's Condition="..." to Condition="false"
Remove line with TypeScriptToolsVersion
Find import of Microsoft.TypeScript.targets and replace it's Condition="..." to Condition="false"
Now after adding file VS will stop trying to do smth with project. And typescript will not be compiled on save and build, so you need to use gulp/webpack/grunt/whatever.
Visual Studio 2019 (16)
Add to *.csproj file
<ItemGroup>
<None Remove="**/*.ts" />
<Content Remove="**/*.ts" />
<TypeScriptCompile Include="**/*.ts" />
</ItemGroup>
Solution is described here: https://developercommunity.visualstudio.com/t/vs-modifies-csproj-file-with-typescriptcompile-ite/288648

Resources