可以使用 $(variableName) 語法引用 Visual Studio 或 MSBuild 變量(如 $(SolutionDir)),以及使用 %VariableName% 來引用環境變量。
介紹幾個常用的$(variableName) 變量:
$(SolutionDir):當前項目所在解決方案目錄
$(ProjectDir):當前項目所在目錄
$(TargetPath):當前項目編譯輸出文件絕對路徑
$(TargetDir):當前項目編譯輸出目錄,即web項目的Bin目錄,控制台、類庫項目bin目錄下的debug或release目錄(取決於當前的編譯模式)
舉個例子:比如我們在D盤根目錄建立了一個控制台項目TestConsole,解決方案目錄為D:\LzrabbitRabbit,項目目錄為
D:\LzrabbitRabbit\TestConsole,那么此時在Debug編譯模式下
$(SolutionDir)的值為D:\LzrabbitRabbit
$(ProjectDir)的值為D:\LzrabbitRabbit\TestConsole
$(TargetPath)值為D:\LzrabbitRabbit\TestConsole\bin\Debug\TestConsole.exe
$(TargetDir)值為D:\LzrabbitRabbit\TestConsole\bin\Debug\
若要創建運行時模板,請向您的項目中添加“已預處理的文本模板”文件。 另外,您還可以添加純文本文件並將其“自定義工具”屬性設置為“TextTemplatingFilePreprocessor”。
若要創建設計時模板,請向您的項目中添加“文本模板”文件。 另外,您還可以添加純文本文件並將其“自定義工具”屬性設置為“TextTemplatingFileGenerator”。
T4基本結構:
T4模板可以分為:指令塊、文本塊、控制塊。
指令塊 - 向文本模板化引擎提供關於如何生成轉換代碼和輸出文件的一般指令。
文本塊 - 直接復制到輸出的內容。
控制塊 - 向文本插入可變值並控制文本的條件或重復部件的程序代碼,不能在控制塊中嵌套控制塊。
6個指令<#@ template #>、<#@ parameter#>、<#@ assembly #>、<#@ import #>、<#@ include #>、<#@ output #>、
其中, output 和 assembly 只能用在設計時模板。
控制塊:
有三種類型的控制塊,根據其左括號對它們進行區分:
1.<# 標准控制塊 #> 可以包含語句。
2.<#= 表達式控制塊 #> 將一個可以計算為字符串的表達式括起來,用於提供要寫入“輸出”文件的字符串的代碼。
3.<#+ 類功能控制塊 #> 可以使用類功能控制塊向文本模板添加方法、屬性、字段甚至是嵌套類。必須作為文件中的最后一個塊顯示,或者用<#@ include #>引入外部文件。
注意:
1)始終使用 {...}花括號來包含內嵌的嵌套語句,否則會報錯。(哪怕花括號中只有一句代碼)
2)控制塊不能互相嵌套。必須先終止之前的控制塊,然后才能打開另一個。
T4文本模板的斷點調試
注冊表:設置DbgJITDebugLaunchSetting值為 2。
(x86系統): HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework
(x64 系統): HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\.NETFramework
為template指令添加debug="true"特性:<#@ template debug="true"#>
命令:
<# System.Diagnostics.Debugger.Launch();#>在模板執行到特定點啟動調試器。如果用Debugger.Break()啟動調試器在調試完后會導致 VS 奔潰。
<#System.Diagnostics.Debugger.Break();#>啟動調試器后,使用此命令在后續特定點處再次進入調試模式,相當於斷點。(此種方式會讓vs崩潰)
使用方法:必須使用“Debugger.Launch()”命令啟動調試器(如下圖,啟動新實例或使用已存在的VS附加。注意,若此處點擊取消則將關閉當前IDE),調試完后可以不用中斷調試,不影響模板編輯,當再次編譯模板時如果存在“Debugger.Break()”命令則自動進入調試模式。
自定義生成的文件存放路徑:
String outputPath = Path.Combine(Path.GetDirectoryName(host.TemplateFile),"Model");
調試的時候發現一個問題:在GetCurrentProject()方法里獲取當前項目dte.ActiveSolutionProjects,第一次生成正常,但是一編譯項目再生成,這里就獲取不到項目了,
Array activeSolutionProjects = (Array)dte.ActiveSolutionProjects 里面是個空數組,導致生成失敗,提示“正在運行轉換: System.IndexOutOfRangeException: 索引超出了數組界限”錯誤。
萬般無奈,只好采用避開調用這里的措施:
在.tt模板里,把定義connectionString、dbProviderName的地方重新寫死。如:
var connectionStringName = "Northwind";
var dbContextName = Host.TemplateFile.Split('\\')[Host.TemplateFile.Split('\\').Length - 1].TrimEnd('.', 't');
//var connectionStringSetting = GetConnectionStringSettings(connectionStringName);
//var connectionString = connectionStringSetting.ConnectionString;
//var dbProviderName = connectionStringSetting.ProviderName;
var connectionString = "Data Source=ZHAOWEI-PC\\SQLEXPRESS;Initial Catalog=Northwind;Persist Security Info=True;User ID=sa;Password=123456";
var dbProviderName = "System.Data.SqlClient";
var dbConfiguration = DbConfiguration.Configure(connectionString, dbProviderName);
var databaseSchema = dbConfiguration.Schema;
var manager = Manager.Create(Host, GenerationEnvironment);
var namespace1 = manager.DefaultProjectNamespace+".Model";
manager.StartHeader();
。。。。
這樣問題暫時解決了。
-------------------------------------------------------------------------------------------------------------
T4模板調試需注意的地方:
1、.tt模板的屬性 自定義工具=TextTemplatingFileGenerator,生成操作=無;
生成的附屬文件屬性 自定義工具=無,生成操作=編譯
2、在下列任何一種情況下,將執行模板,同時生成附屬文件:
編輯該模板,然后將焦點更改到其他 Visual Studio 窗口。
保存模板。
單擊“生成”菜單中的“轉換所有模板”。 這將轉換 Visual Studio 解決方案中的所有模板。
在“解決方案資源管理器”中,在任何文件的快捷菜單上,選擇“運行自定義工具”。 使用此方法可以轉換選定的模板子集。
<#@ import namespace="EnvDTE" #>
EnvDTE路徑:
C:\Program Files (x86)\Common Files\microsoft shared\MSEnv\PublicAssemblies
<#@ Assembly Name="C:\Program Files (x86)\Common Files\microsoft shared\MSEnv\PublicAssemblies\envdte.dll" #>
<#@ Import namespace="EnvDTE80" #>
<#@ Import namespace="EnvDTE90" #>
<#@ Import namespace="EnvDTE90a" #>
<#@ Import namespace="EnvDTE100" #>
private EnvDTE.Project getActiveProject(EnvDTE.DTE dte)
{
Array projects = dte.ActiveSolutionProjects as Array;
if (projects == null || projects.Length == 0)
{
projects = dte.Solution.SolutionBuild.StartupProjects as Array;
if (projects == null || projects.Length == 0)
{
EnvDTE.Projects pro = dte.Solution.Projects;
if (pro == null || pro.Count == 0)
return null;
return pro.Item(0);
}
}
return projects.GetValue(0) as EnvDTE.Project;
}
public Project getActiveProject()
{
Array projects = (Array)_applicationObject.ActiveSolutionProjects;
if(projects != null && projects.Length > 0)
{
return projects.GetValue(0) as Project;
}
projects = (Array)_applicationObject.Solution.SolutionBuild.StartupProjects;
if(projects != null && projects.Length >= 1)
{
return projects.GetValue(0) as Project;
}
projects = (Array)_applicationObject.Solution.Projects;
if(projects != null && projects.Length > 0)
{
return projects.GetValue(0) as Project;
}
return null;
}
待解決問題:
(Array)dte.ActiveSolutionProjects IndexOutOfRangeException
(Array)dte.ActiveSolutionProjects 索引超出了數組界限
參考:
https://msdn.microsoft.com/zh-cn/library/gg604090
https://msdn.microsoft.com/zh-cn/library/dd820620
http://www.cnblogs.com/guohu/p/4541418.html
http://blog.chenxu.me/post/detail?id=2c393950-acbe-4367-8039-a326449c8d22
https://social.msdn.microsoft.com/Forums/vstudio/en-US/4b746a30-9f6f-446b-9e1e-54b5ba3f29b7/activesolutionprojects-indexoutofrange?forum=vsx