I am using T4toolbox to generate a bunch of files, let's say my t4 file name is x.t4, but default it generate a x.txt, which has nothing inside, can I tell t4 engine not to do this?
Found a trick/hack!
<## output extension="/" #>
or
<## output extension="\\" #>
Visual Studio neither outputs the default file nor complains about its inability too much.
If you want to avoid warnings, you can also modify output path through the extension:
<## output extension="xml/../_" #>
The file will still be created and attached to the T4 file within the project hierarchy in Visual Studio, but you can put it into any directory.
P.S. I've tried it with T4MultiFile NuGet package, but it should work with T4Toolbox too, I think.
Right click on x.t4 in Solution Explorer and click Properties. It will say "TextTemplatingFileGenerator" beside Custom Tool. Delete this.
x.t4 will now be part of your project but it will not generate anything. This is useful when the .t4/.tt file is only being used as an include file in other templates.
No. This file is created by Visual Studio and not by T4. The best you can do is generate something useful in it such as actual code or, perhaps, a log of the code generation run.
Related
Wanted to pick the brains of those MS Build/ VS Post build exponents here.
I would like to have my web.config entries customizable per user/machine/environment.
I could have my configurable/changeable entries marked in the web.config and would like those entries overridden by the respective user/environment file and would like to have an order that decides which entries should trump the other if the entry is found in multiple files.
for eg: web.config has a $connectionstring entry and the customization files per user/environment could have the potential values to replace $connectionstring depending on the context/configuration the solution is built
which means, I could have a set of files like below:
user_joe.config
$connectionstring = db_where_joe_like_to_connect_to
staging.config
$connectionstring = db_where_staging_connect_to
production.config
$connectionstring = db_production
so if joe is compiling the solution from his Dev box, the web.config should have the value "db_where_joe_like_to_connect_to" for $connectionstring.
I am hoping there could be a solution that doesn't involve Nant.
hope someone can throw pointers.
You can use visual studio 2010's web.config transform settings.
http://weblogs.asp.net/gunnarpeipman/archive/2009/06/16/visual-studio-2010-web-config-transforms.aspx
This will allow each developer to have their portion of a web.config that can get merged in for their build settings.
Internally we use an event that was pieced together from various places on the net- since normally this happens during publishing and we wanted it to happen at compile time.
Add a BeforeBuild target
So - from the csproj file:
<Target Name="BeforeBuild">
<TransformXml Source="$(SolutionDir)Web.config" Transform="$(SolutionDir)Web.$(Configuration).config" Destination="$(SolutionDir)Web.$(Configuration).config.transformed" />
</Target>
<PropertyGroup>
<PostBuildEvent>xcopy "$(SolutionDir)Web.$(Configuration).config.transformed" "$(SolutionDir)Web.config" /R /Y</PostBuildEvent>
</PropertyGroup>
I would suggest using the configSource attribute in the web.config entries for debug builds. Then, in your test and releae builds you can use data transformations to insert the testing and production entries.
You would do something like this:
<connectionStrings configSource="myLocalConnectionStrings.cfg" />
Then you have a local file called myLocalConnectionStrings that you don't check into source control. In your Web.config.Release you simply transform the connectionStrings section to include the production strings and remove the configSource attribute.
As Adam said in his answer, you can kind of do this using web.config transforms. Basically you'd have to create a new solution configuration for each environment. Note that having one for each developer will likely quickly become unmaintaniable, as each configuration / platform combination can have it's own build settings.
Also, the transforms are ONLY applied during the web site packaging (calling the Package target). So if you're trying to use this so that joe and sally can have different configs on their own machine, this won't do that for you.
In that case you're probably better off trying to get everyone on the same configuration, than allowing configs to fragment. The more differences between each environment, the harder time you'll have deploying.
Here is a T4 solution. This worked for my case because this was an internal tool that would only be used by developers and because I don't need further processing for the "included" files.
File name App.tt.
<## template debug="false" hostspecific="true" language="C#" #>
<## import namespace="System" #>
<## import namespace="System.IO" #>
<## output extension=".config" #>
<#
string pathToConfigurations = Host.ResolvePath("Configurations");
string pathToMachine = Path.Combine(pathToConfigurations, Environment.MachineName + ".config");
if (File.Exists(pathToMachine))
{
Write(File.ReadAllText(pathToMachine));
}
else
{
Write(File.ReadAllText(Path.Combine(pathToConfigurations, "App.config")));
}
#>
How can I specify the output path of a T4 template?
When I add my T4 template using "Add as Link" to my project from $TemplatePath$, it generates the output file in $TemplatePath$, not $ProjectPath$. How can I specify that $ProjectPath is where the generated file is placed?
I got around this by having a master template in one location and then templates that imported that one (but did little else) in each project. Of course, that's not the nicest solution.
We typically use the same system that Jeff Yates mentioned with minimal (often single line) stub templates including the shared template.
You could also use Oleg Sych's T4Toolbox to project output to any directory you please.
However, the standard IVsSingleFileGenerator that T4's custom tool is built upon doesn't have any dials to turn to control it's output location and it's behavior in the case of linked files is as you describe.
I would like to know if is possible to run a T4 template when saving a other file, example run my .tt file after/on saving a xml file
I forgot to mention that my IDE is VS2010
Yes, it is possible. Here is how.
I use ILMerge to merge several of my C# project DLLs into a single DLL for the whole solution. I have each project produce a .XML file of its documentation for Intellisense, and I'm having trouble getting those comments to show up when I try to use my merged DLL as a reference in another solution. I have these files all in the same directory:
MergedProjectDlls.dll
Project1.XML
Project2.XML
Project3.XML
Project4.XML
I tried renaming a single project XML file to be MergedProjectDlls.XML then removing and re-adding the reference in Visual Studio, but Intellisense still wasn't picking up on the comments that I know are there in the project XML file I renamed.
I was hoping to somehow merge all these project XML files into one titled MergedProjectDlls.XML anyway. Is that possible? Would Intellisense then pick up on it automatically when it's in the same directory as MergedProjectDlls.dll?
Edit: just found this on MSDN:
To use the generated .xml file for use with the IntelliSense feature, let the file name of the .xml file be the same as the assembly you want to support and then make sure the .xml file is in the same directory as the assembly. Thus, when the assembly is referenced in the Visual Studio project, the .xml file is found as well.
And also:
Unless you compile with /target:module, file will contain tags specifying the name of the file containing the assembly manifest for the output file of the compilation."
Der, it turns out that's just a command-line option to ILMerge:
ILMerge.exe /out:MergedProjectDlls.dll
Project1.dll Project2.dll Project3.dll
Project4.dll /ndebug /xmldocs
I wanted to use T4 to generate properties for a partial class. I'm running into a configuration problem where my .TT file is in the same project as the class file I want to extend. So if I have to include the assembly in the .TT file it get's locked. I tried to do a command line in the pre-build but the problem there is that VS always wants to recompile the .TT file with the project.
The only solution I can think of is to rename the .tt files to say .t4 and then use a pre-build command with TextTransform -out to create the .cs file in the project directory.
Can anyone think of a cleaner way to do this?
Assuming that locking is caused by your template using Reflection to read metadata of the partial class you need to extend, you could solve the locking problem if you use CodeModel. This API is provided by Visual Studio and allows you to get the metadata directly from the source file, without the need to compile the partial class or load the compiled DLL. Here is an example of a T4 code generator that uses this approach: http://www.olegsych.com/2008/07/t4-template-for-generating-sql-view-from-csharp-enumeration