Automatically regenerate Text Templates that depends upon multiple files - visual-studio

My situation:
I have a VS 2010 project with 3 files:
content.txt
generator.tt
generated.js (generated via T4)
The project file contains them as:<None Include="generator.tt">
<Generator>TextTemplatingFileGenerator</Generator>
<LastGenOutput>generated.js</LastGenOutput>
</None>
<Content Include="content.txt" />
<Content Include="generated.js">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>generator.tt</DependentUpon>
</Content>
The generated.js will be regenerated on every change of generator.tt
is there a way to automatically regenerating generated.js on changes to one of the other files (without using any plugin)?
I've tried to simply add another DependentUpon Element. But VS only takes care of the last one...
Thanks for your ideas
Edit:
I've forgotten one detail:
- The solution has to work with TFS. So it has to do a "Check Out for Edit..." when files are modified.

Related

Where are ASP.NET temporary files stored in Kestrel?

On our dot net core project we are using ViewComponents.
When we change the View referenced by one of our ViewComponents, when "dotnet run watch" is running the end result does not update until we restart dotnet. Creating a new view with the same code which our view component uses, causes it to update and works. This is very frustrating when trying to debug an error only to remember you need to restart dotnet
Can someone please tell me how we can force recompile or ignore certain directories from this cache?
This is happening on .netcoreapp 1.1 on OSX
dotnet-watch keeps an in-memory list of files that it is watching. You can inspect this list by running dotnet watch --list.
By default, dotnet-watch only restarts the process when Compile and EmbeddedResource items change. This normally only includes *.cs and *.resx files, but may include other files depending on your project.
To exclude a folder, you can set "Watch=false" on these items.
<ItemGroup>
<Compile Update="ignored_dir\**\*.cs" Watch="false" />
</ItemGroup>
You can explicitly add new filetypes to watch by adding <Watch> items to your *.csproj file. Examples:
<ItemGroup>
<Watch Include="*.js" />
<Watch Include="somefile.txt" />
<Watch Include="subdir\**\*" />
</ItemGroup>
Just for clarity's sake, dotnet-watch is independent of Kestrel.
For more details, see https://github.com/aspnet/DotNetTools/tree/1.0.1/src/Microsoft.DotNet.Watcher.Tools#msbuild

Unwanted changes in .csproj file on build

I'm trying to auto-detect web.configs as part of a transform pre-build event in one of my web application project files, this code goes up one folder level from my project file and gets all web.configs in every directory and sub directory:
<ItemGroup>
<WebConfigsRelativePath Include ="..\**\Web.config"/>
</ItemGroup>
This works great but everytime I build and exit Visual Studio, I get a prompt asking me if I want to save changes made to my solution file. If I select yes, and open the project file, the above code is changed to the locations of each web.config
<ItemGroup>
<WebConfigsRelativePath Include="..\Web\Decade\Web.config" />
<WebConfigsRelativePath Include="..\Web\Matrix\RiskAnalysis\Web.config" />
<WebConfigsRelativePath Include="..\Web\Service\Web.config" />
<WebConfigsRelativePath Include="..\Web\Web.config" />
</ItemGroup>
This would be fine but the whole reason I'm auto-detecting web.configs pre-build is so I can add and remove web.configs as I please without having to hardcode their locations, and everytime I exit VS, the locations will be hardcoded in the project file....
Does anyone know why this ItemGroup changes every time I exit Visual Studio?
If I take an existing web project but use the <Content /> rather than the custom <WebConfigsRelativePath /> in your sample, then I see the expected behavior.
Try using this:
<Content Include="..\**\Web.config">
<SubType>Designer</SubType>
</Content>
Edit:
If you have special handling for the WebConfigsRelativePath item group, post that in an update to your question.
While I can't explain why VS decides to output a list of files retrieved by the wildcard each time my solution is built, I can show you how I got around this issue:
<PropertyGroup>
<WebConfigsSearchString>..\**\Web.config</WebConfigsSearchString>
</PropertyGroup>
<ItemGroup>
<WebConfigsRelativePath Include ="$(WebConfigsSearchString)"/>
</ItemGroup>
By defining the search string in a property (which always stays static) and referencing the property in the item group's list of files to include, the item group code is never modified but the web.config search is carried out each time a build is run

Group files in Visual Studio

I'm looking at tidying up my project layout in Visual Studio and I'm wondering if there is any hack, plugin or trick to associate an .xml file with a .cs file of the same name so they appear grouped in my solution navigator/explorer.
Similar to the way the code-behind file is associated with its aspx.
Any suggestions welcome. Thanks
In your project file :
<Compile Include="FileA.cs"/>
<Compile Include="FileA.xml">
<DependentUpon>FileA.cs</DependentUpon>
</Compile>
Or you could use Group Items command of VSCommands 2010 extension.
Edit: Just in case your file is in a folder, don't include the folder name in DependentUpon tag. For example if your file is in Helpers folder:
<Compile Include="Helpers\FileA.cs"/>
<Compile Include="Helpers\FileA.xml">
<DependentUpon>FileA.cs</DependentUpon>
</Compile>
If you do not want to slow down you IDE with heavy and proprietary VSCommands extension you can use small extension NestIn instead. It can nothing but group/ungroup files
In .NET (Core+)
<ItemGroup>
<Compile Update="FileA.*.cs">
<DependentUpon>FileA.cs</DependentUpon>
</Compile>
</ItemGroup>
Note that Update is used instead of Include where files are already (implicitly) included in the project and use of Include causes compile-time "Error NETSDKxxxx Duplicate 'Compile' items were included... The duplicate items were: 'FileA.xxxx.cs' C:\Program Files\dotnet\sdk\x.x.x.x\Sdks\Microsoft.NET.Sdk\targets\Microsoft.NET.Sdk.DefaultItems.Shared.targets"
See Is there a DependentUpon option in a .net core app?
For the simple case where the file is a "top level" file, Julien's description works perfectly. However, in the case where the DependentUpon file is in a Folder under the project, this looks different. I personally don't like it because it seems like it could lead to ambiguity, but that's an opinion.
<Compile Include="DataStructs\CKDTree.cs" />
<Compile Include="DataStructs\CClosestObjects.cs" >
<DependentUpon>CKDTree.cs</DependentUpon>
</Compile>
Notice that the dependent item does NOT include the Folder of the parent. This is true in VS2013... probably true in earlier versions but I have not verified it.
File Nesting extension for visual studio is a good one. It has about 500K downloads at the time of writing this answer. I added it personally to my VS 2015 and it was working fine (haven't tried it with VS 2017 yet).
Not sure if people are aware, but nesting files like this seemingly breaks VS's ability to rename the root file, at least when your new nested file is also a partial class. For instance here's the tree we created...
MainWindow.xaml
MainWindow.xaml.cs
MainWindow.Commands.cs
MainWindow.Commands.cs is just another partial class of MainWindow, same as MainWindow.xaml.cs. However, if you then try and rename MainWindow.xaml, instead of automatically renaming the dependent files, it throws an exception.
For completeness, I also tried naming the file MainWindow.xaml.Commands.cs but that didn't work either.
Without the extra 'commands' file, rename works fine, of course.
MainWindow.xaml
MainWindow.xaml.cs
Anyway, this was reason enough for us to abandon nesting files like this. Without the ability to rename, it's just not worth it.

"Add as Link" for folders in Visual Studio projects

In Visual Studio, we can "Add as link" to add a link to a file in another project in the solution.
Is there any way to do this for entire folders, so that an entire folder in project A will be visible in project B, without the need to manually link to new items in that folder?
As this blogpost stated, it is possible.
<ItemGroup>
<Compile Include="any_abs_or_rel_path\**\*.*">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
</ItemGroup>
But be aware, the files will not be copied.
In VS2012 and later, you can drag a folder to another project with alt key pressed. It's just the same as adding each file as link manually but faster.
upd:
Consider using Shared Projects if you are using VS2013 update 2 (with Shared Project Reference Manager) or VS2015.
One addition to the answer from mo. and the comment from Marcus, if you are linking content items you will need to include the file extension:
<ItemGroup>
<Compile Include="any_abs_or_rel_path\**\*.*">
<Link>%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Compile>
</ItemGroup>
Regarding the part of the original query to have a linked folder appear in the IDE, it is kind of possible to achieve this so there is a folder in the solution explorer with all linked files inside, instead of all the files appearing in the root of the solution. To achieve this, include the addition:
<ItemGroup>
<Compile Include="..\anypath\**\*.*">
<Link>MyData\A\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Compile>
</ItemGroup>
This will include all files from the linked directory in a new folder in the solution explorer called MyData. The 'A' in the code above can be called anything but must be there in order for the folder to appear.
If you want to add a folder as a reference and you don't want to compile it, use:
<Content Include="any_path\**\*.*">
<Link>folder_in_B_project\%(RecursiveDir)%(FileName)%(Extension)</Link>
</Content>
Even when there are so many solutions it took me a while to understand it. Here I will try to explain it a little bit more.
I needed link to the whole folder so my final result is:
<ItemGroup>
<Content Include="..\Gym.Management.Api\TestFolder\**\*.*">
<Link>TestFolder\%(RecursiveDir)%(FileName)%(Extension)</Link>
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
where:
..\Gym.Management.Api\TestFolder\ represents path to the other project containing the folder I want to link
TestFolder\ in <link> tag is the final(destination) folder in my current project where I want to link it
TIP:
When you are not sure how to get the proper Include path then in your current project right click on project->click Add->Existing item->navigate to one of those files from folder you want to link-> instead of Add, press the dropdown arrow next to it->click Add as link.
This link is inserted in your .csproj file and from there you can extract the Include path.
If what you are looking for is to add another folder to your current workspace for easy access & development experience.
you can do this by just clicking file -> Add Folder to Workspace option in vscode.
Bust out the shell and add a symbolic link.
runas Administrator then
mklink /d LinkToDirectory DirectoryThatIsLinkedTo
BAM symbolic link!
/d specifies directory link.
Works in Vista on up out of the box. Can be backported to XP.
Documentation here: http://technet.microsoft.com/en-us/library/cc753194%28WS.10%29.aspx
For those not familiar with symbolic links, it's essentially a pointer to another file or directory. It's transparent to applications. One copy on disk, several ways to address it. You can also make a "hard link" which is not a pointer to another address, but an actual file ID entry in NTFS for the same file.
NOTE: as stated in the comments, this would only work on the computer where you created the symlink and wouldn't work in a Version Control System like git.

In Visual Studio, how can I set the Build Action for an entire folder?

I have a project in Visual Studio. I need to deploy some 3rd party files along with my code. Typically I would put this files in a "Resources" directory and set the Build Action on each file to "Content" and the Copy To Output Directory to "Copy if newer".
Is there anyway I can set these directives at the folder level. The current project I am working with has dozens of such files and a couple of sub folders. I'd like to be able to make the entire directory as "Content" and "Copy if newer".
Create the project. Add one file as Content. Unload the project and edit the *proj file manually.
<ItemGroup>
<Content Include="myfolder**\*.dll**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
And then in the content-ItemGroup I would replace that singe file with some MsBuild wildcard expression, *.dll, or whatever.
I use Visual Studio 2012 and you can shift-click to select multiple items in the Solution Explorer then edit each item's Copy To Output Directory property all at once in the Properties window.
Granted this isn't equivalent to the solution you are looking for functionally, but semantically it is. And hopefully the next person to stumble across this post with a humongous folder to remedy (as is with me) won't have to dive into the .csproj file.
Hope this helps!
If you happen to have the need to set the Build Action for an entire folder the best option is to just open the .csproj file and use a regex to replace all the occurences from
<Content ....
to
<None ...
That worked just perfectly for me.
I just added this to my *.csproj file (right click Edit Project File)
<ItemGroup>
<Content Include="MYCUSTOMFOLDER\**">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
I know this answer is similar to #Arve but I don't know why this extra complexity with the .dll wildcard filter.
Edit your *.csproj or .vbproj file
Add this tag
<ItemGroup>
<Folder Include="YOUR_FOLDER_NAME_HERE/">
</ItemGroup
the final file must look like this:
<Project>
<---some more tags--->
<ItemGroup>
<Folder Include="YOUR_FOLDER_NAME_HERE\" />
</ItemGroup
<---some more tags--->
</Project>
If you want to preserve the recursive folder structure it is possible to add this piece of XML:
<ItemGroup Label="bg_screens">
<_CustomResource Include="..\..\resourcedir\**\*">
<Link>resourcedir\%(RecursiveDir)%(FileName)%(Extension)</Link>
<DeploymentContent>true</DeploymentContent>
</_CustomResource>
</ItemGroup>
The the resources will keep the tree structure instead of being added in a flat manner.

Resources